Arduino Learning Studiorobotics pathway

R14-U3 · usually age 14 · Robotics Engineers

Data and Tuning

What do logged results tell us?

Pilot unit plan · 5 sessions · not yet classroom-validated

Build: Tuned navigation controller

What the logs say: the sampling interval and the size of one count, encoder noise seen in plots, a CSV log copied into a spreadsheet and graphed, saved and dated sketch versions with a change note, and controller settings tuned one change at a time and judged by before/after graphs.

  • Sense
  • Test and debug

Who it is for

Age is a starting point, never a limit. A learner who can show what this unit starts from can begin here at any age.

How they learn
By reading and changing real Arduino sketches, predicting, testing in a model, then building and testing the real circuit.
The adult's role
An adult checks every circuit and anything that moves before it is powered.
Session
75–90 minutes
Hardware
Arduino Uno R3 or compatible (5 V). The adult checks the power circuit and the motor driver. Motors never run from a pin; share GND between supplies.

Starts from

Builds, and what it is the input for

In the studio today

No studio lab or activity for this unit yet.

Sessions

  1. Session 1 · 80 min

    How often should the rover measure?

    Sampling: the controller sees each wheel once per interval. A short interval gives few counts per sample, so one count more or less is a big jump in cm/s (noise from counting); a long one is smoother but reacts late. The speed and error are in cm/s, so a new interval changes the noise, not what Kp means. The encoder's own noise: uneven slots, a wobbling disc, a SIG wire run beside the motor leads (keep them apart), and light from outside (the datasheet asks for the sensor's detecting face to be kept away from external light; its detector is most sensitive at 900 nm, in the infrared). The sensor has hysteresis built in (the datasheet gives IFHL/IFLH as 0.55 to 0.95): its output goes HIGH at one light level and back LOW only at a lower one, so a slot edge passing slowly gives one clean change, not a burst. Seeing it: the Serial Plotter draws each labelled value as a line.

    In the studio

    No studio lab: this session is off-screen.

    Hands-on

    Start from your R14-U2 session 5 sketch with Kp = 0 and print, on each sample, labelled values for the Serial Plotter: target:, left: and right:, separated by commas, with Serial.println() at the end. Upload, then open the Serial Plotter before the motor battery goes on, as you do with the Serial Monitor. Lift the rover, wheels in the air, and run at one steady value with the sample interval at 50, 100 and 200 ms. For each, note the lowest and highest speed in steady running and how many counts one sample holds. Then, wheels still lifted, the adult holds an incandescent torch (never a hot halogen lamp) at the open side of one sensor, away from the wires, while you watch the plot for extra or missing counts. The detector is most sensitive at 900 nm, in the infrared, so an LED torch may show no effect; "no effect" is a valid result.

    Starting code: The learner's own sketch from R14-U2 session 5, with Kp = 0 and labelled values printed for the Serial Plotter.

    Pins

    D2
    left wheel encoder SIG (photo interrupter breakout)
    D3
    right wheel encoder SIG (photo interrupter breakout)
    D4
    driver AIN1 (left motor)
    D5
    driver PWMA (left motor)
    D6
    driver PWMB (right motor)
    D7
    driver AIN2 (left motor)
    D8
    driver STBY moved from D3
    D9
    HC-SR04 Trig (wired, not read; kept OUTPUT and LOW)
    D10
    HC-SR04 Echo (wired, not read in these sketches)
    D11
    driver BIN2 (right motor)
    D12
    driver BIN1 (right motor)
    A0
    STOP button (other side to GND) moved from D2

    Evidence to collect

    A sampling table (interval → counts per sample, lowest and highest steady speed in cm/s, how late a change shows), a drawing or screenshot of the plot at two intervals (the rover only, no people), and a note on what the torch did, "no effect" included.

    Predict
    Which interval will make the plotted speed the most jagged?
    Debug
    If the Serial Plotter draws nothing, check that each line ends with Serial.println() and that its baud rate matches Serial.begin().
    Reflect
    Which interval would you give the controller, and what does it cost?

    ⚠ Adult checks before power-on: Before every upload: setup() never sets pin 2 or 3 as OUTPUT (the encoders drive those pins). The motor battery reaches the driver's VM only, through its power-off switch; the board's 5V goes to the driver's VCC only; every GND is joined. Lifted, wheels in the air, for every run in this session. The torch is incandescent, never a hot halogen lamp, held by the adult clear of the wheels and the wires. Fingers and hair clear of wheels and discs while the motor battery is on. Lift the rover (wheels in the air) before switching the motor battery back on: the sketch keeps running on USB, so the wheels take its last command at once.

    Works towards: Data-driven tuning

  2. Session 2 · 90 min

    Can a log become a graph?

    CSV logging: a header line first (time_ms,target,left,right,valueL,valueR), then one line per sample with the values separated by commas; copied from the Serial Monitor into a spreadsheet, split into columns and drawn as a line chart against time. Reading the graph: how long the speed takes to reach the target, how far it overshoots, and how much it wobbles once settled.

    In the studio

    No studio lab: this session is off-screen.

    Hands-on

    Start from your session 1 sketch, with the controller back on, and print a header line in setup() and one comma-separated line per sample. Set Serial.begin() and the Serial Monitor to the same faster baud rate from the menu, such as 115200, so printing keeps up. Keep the stall rule in the drive state. Upload, open the Serial Monitor before the motor battery goes on (opening it restarts the UNO), run it lifted once, then run one closed-loop start on the 2 m line, never above 160 of 255. Switch the motor battery off, select the lines in the Serial Monitor, copy them into a spreadsheet and split them at the commas. Check the time column: gaps longer than the interval mean printing is holding loop() up. Draw speed and target against time, and mark the time to reach the target, the overshoot and the wobble.

    Starting code: The learner's session 1 sketch, with the controller back on and a comma-separated line per sample.

    Pins

    D2
    left wheel encoder SIG (photo interrupter breakout)
    D3
    right wheel encoder SIG (photo interrupter breakout)
    D4
    driver AIN1 (left motor)
    D5
    driver PWMA (left motor)
    D6
    driver PWMB (right motor)
    D7
    driver AIN2 (left motor)
    D8
    driver STBY moved from D3
    D9
    HC-SR04 Trig (wired, not read; kept OUTPUT and LOW)
    D10
    HC-SR04 Echo (wired, not read in these sketches)
    D11
    driver BIN2 (right motor)
    D12
    driver BIN1 (right motor)
    A0
    STOP button (other side to GND) moved from D2

    Evidence to collect

    The CSV log, the graph with labelled axes (time in ms; speed in cm/s), and the three numbers read from it: time to reach the target, overshoot and wobble.

    Predict
    Sketch the graph you expect before the run: where will the speed overshoot?
    Debug
    If the spreadsheet puts everything in one column, split the text at the commas; if a row is short, look for a line cut in half.
    Reflect
    What does the graph show that the numbers in the Serial Monitor did not?

    ⚠ Adult checks before power-on: Before every upload: setup() never sets pin 2 or 3 as OUTPUT (the encoders drive those pins). The motor battery reaches the driver's VM only, through its power-off switch; the board's 5V goes to the driver's VCC only; every GND is joined. Every value the controller can send passes through constrain(…, 0, 160): check that line before the upload. Lifted for the first run of every new sketch; on the floor never above 160 of 255, on a clear floor with the power-off switch in reach. The stall rule: in every driving state, go to STOPPED if a wheel's count is unchanged for 5 samples while its value is above its measured start value, or if the segment runs over twice its measured time. The USB cable is held clear of the wheels by the adult. Fingers and hair clear of wheels and discs while the motor battery is on. Lift the rover (wheels in the air) before switching the motor battery back on: the sketch keeps running on USB, so the wheels take its last command at once.

    Works towards: Data-driven tuning

  3. Session 3 · 80 min

    What changed between versions?

    Versions: every change worth testing is saved as a new sketch with Save As, named with a version and the date, such as rover_v03_2026-11-14 (the sketch's folder takes the same name), with a change note in its first comment lines: version, date, what changed, why, and the result once tested. Old versions are never edited, so any result can be repeated. If the school has git, one commit per change with a message saying what and why does the same job.

    In the studio

    No studio lab: this session is off-screen.

    Hands-on

    Start a version table in the notebook: version, date, change, reason, result. Save your session 2 sketch as version 1 with today's date and a change note, and print its version in setup(). Make one change, the sample interval you chose in session 1, save it as version 2 with its note, and upload it. Open the Serial Monitor before the motor battery goes on (opening it restarts the UNO); run session 2's test lifted once, then on the floor never above 160 of 255, with the stall rule kept, and graph it beside version 1's. Then open version 1 again, upload it, and run it once more: does it give the same graph as before?

    Starting code: The learner's session 2 sketch, saved as version 1 with a change note.

    Pins

    D2
    left wheel encoder SIG (photo interrupter breakout)
    D3
    right wheel encoder SIG (photo interrupter breakout)
    D4
    driver AIN1 (left motor)
    D5
    driver PWMA (left motor)
    D6
    driver PWMB (right motor)
    D7
    driver AIN2 (left motor)
    D8
    driver STBY moved from D3
    D9
    HC-SR04 Trig (wired, not read; kept OUTPUT and LOW)
    D10
    HC-SR04 Echo (wired, not read in these sketches)
    D11
    driver BIN2 (right motor)
    D12
    driver BIN1 (right motor)
    A0
    STOP button (other side to GND) moved from D2

    Evidence to collect

    The version table with two versions and their change notes, the two graphs side by side with the version on each, and the rerun of version 1 compared with its first graph.

    Predict
    Will rerunning version 1 give exactly the same graph? Why or why not?
    Debug
    If you cannot tell which sketch made a graph, the version is missing from the log: print it in setup().
    Reflect
    What would you lose if you had kept editing one sketch?

    ⚠ Adult checks before power-on: Before every upload: setup() never sets pin 2 or 3 as OUTPUT (the encoders drive those pins). The motor battery reaches the driver's VM only, through its power-off switch; the board's 5V goes to the driver's VCC only; every GND is joined. Every value the controller can send passes through constrain(…, 0, 160): check that line before the upload. Lifted for the first run of every new sketch; on the floor never above 160 of 255, on a clear floor with the power-off switch in reach. The stall rule: in every driving state, go to STOPPED if a wheel's count is unchanged for 5 samples while its value is above its measured start value, or if the segment runs over twice its measured time. The USB cable is held clear of the wheels by the adult. Fingers and hair clear of wheels and discs while the motor battery is on. Lift the rover (wheels in the air) before switching the motor battery back on: the sketch keeps running on USB, so the wheels take its last command at once.

    Works towards: Versions and changes, Data-driven tuning

  4. Session 4 · 90 min

    Which setting is best, by the data?

    Tuning with data, one change at a time: one setting (Kp, then the sample interval) changed per version, three runs per version on the same course, judged by the numbers read from the graphs (time to the target, overshoot, wobble and drift at 2 m), never by one run or by eye. A worse result stays in the table too. A Kp that swung lifted never goes on the floor.

    In the studio

    No studio lab: this session is off-screen.

    Hands-on

    Start from your session 3 sketch (version 2). Plan two versions, each changing one setting from the version before: version 3 with Kp halved, then version 4 with the better Kp of versions 2 and 3 and the other sample interval you considered. Doubling Kp is not tried: R14-U2's procedure already found it swings. For each: save it with its change note, upload, open the Serial Monitor before the motor battery goes on (opening it restarts the UNO), run it lifted once, and if it swings lifted, note it in the table and do not take it to the floor; otherwise run three logged starts on the 2 m line, never above 160 of 255, with the stall rule kept; graph them and fill in the numbers. Choose a version by the numbers and write why.

    Starting code: The learner's session 3 sketch (version 2), saved as a new version for each of the two changes.

    Pins

    D2
    left wheel encoder SIG (photo interrupter breakout)
    D3
    right wheel encoder SIG (photo interrupter breakout)
    D4
    driver AIN1 (left motor)
    D5
    driver PWMA (left motor)
    D6
    driver PWMB (right motor)
    D7
    driver AIN2 (left motor)
    D8
    driver STBY moved from D3
    D9
    HC-SR04 Trig (wired, not read; kept OUTPUT and LOW)
    D10
    HC-SR04 Echo (wired, not read in these sketches)
    D11
    driver BIN2 (right motor)
    D12
    driver BIN1 (right motor)
    A0
    STOP button (other side to GND) moved from D2

    Evidence to collect

    A tuning table: version → the setting changed → whether it swung lifted → time to the target, overshoot, wobble and drift (each the mean of three runs), with the graphs, and the chosen version with the reason.

    Predict
    Which of the two versions will have less overshoot, and which less drift?
    Debug
    If two runs of one version differ more than two versions do, the test is not repeatable yet: fix the start position or the floor first.
    Reflect
    Did the best version for overshoot also win on drift?

    ⚠ Adult checks before power-on: Before every upload: setup() never sets pin 2 or 3 as OUTPUT (the encoders drive those pins). The motor battery reaches the driver's VM only, through its power-off switch; the board's 5V goes to the driver's VCC only; every GND is joined. Every value the controller can send passes through constrain(…, 0, 160): check that line before the upload. Lifted for the first run of every new sketch; on the floor never above 160 of 255, on a clear floor with the power-off switch in reach. A version that swung lifted does not run on the floor. The stall rule: in every driving state, go to STOPPED if a wheel's count is unchanged for 5 samples while its value is above its measured start value, or if the segment runs over twice its measured time. The USB cable is held clear of the wheels by the adult. Fingers and hair clear of wheels and discs while the motor battery is on. Lift the rover (wheels in the air) before switching the motor battery back on: the sketch keeps running on USB, so the wheels take its last command at once.

    Works towards: Data-driven tuning, Versions and changes

  5. Session 5 · 90 min

    What do the before and after graphs show?

    A before/after report: R14-U2's controller and the tuned version on the same test, plotted on the same axes, with the numbers, the spread over the runs and both change notes; and what the data cannot tell.

    In the studio

    No studio lab: this session is off-screen.

    Hands-on

    Start from your chosen version, unchanged during the trials, and R14-U2 session 5's version (saved, not edited). Measure the motor battery on DC volts at the breadboard rails it feeds: below 5.0 V, replace the cells before any run (the driver's 1.0 A rating needs VM≥5V; a run-down alkaline pack also falls below 5 V). Open the Serial Monitor before the motor battery goes on (opening it restarts the UNO). Run five logged starts of each on the 2 m line, alternating the two versions, never above 160 of 255, both with the stall rule. Plot the before and after runs on the same axes and fill in the numbers.

    Starting code: The learner's own sketch: the chosen version and R14-U2 session 5's version, both unchanged.

    Pins

    D2
    left wheel encoder SIG (photo interrupter breakout)
    D3
    right wheel encoder SIG (photo interrupter breakout)
    D4
    driver AIN1 (left motor)
    D5
    driver PWMA (left motor)
    D6
    driver PWMB (right motor)
    D7
    driver AIN2 (left motor)
    D8
    driver STBY moved from D3
    D9
    HC-SR04 Trig (wired, not read; kept OUTPUT and LOW)
    D10
    HC-SR04 Echo (wired, not read in these sketches)
    D11
    driver BIN2 (right motor)
    D12
    driver BIN1 (right motor)
    A0
    STOP button (other side to GND) moved from D2

    Evidence to collect

    The unit's evidence: provide graphs with before/after measurements. The before and after graphs on the same axes; a table of the five runs of each (time to the target, overshoot, wobble, drift at 2 m, with the mean and spread); the battery readings; and both versions' change notes.

    Predict
    By how much will the tuned version beat the old one, and on which number?
    Debug
    If the before runs look better than they did in R14-U2, check the battery reading and the floor: something besides the sketch changed.
    Reflect
    What can these graphs not tell you about the rover?

    ⚠ Adult checks before power-on: Before every upload: setup() never sets pin 2 or 3 as OUTPUT (the encoders drive those pins). The motor battery reaches the driver's VM only, through its power-off switch; the board's 5V goes to the driver's VCC only; every GND is joined. For the reading: red lead in the V/Ω socket, never 10A; probes go on breadboard rows or rails, not at the header pins. The battery reads at least 5.0 V before the trials. Every value the controller can send passes through constrain(…, 0, 160): check that line before the upload. Lifted for the first run of every new sketch; on the floor never above 160 of 255, on a clear floor with the power-off switch in reach. The stall rule: in every driving state, go to STOPPED if a wheel's count is unchanged for 5 samples while its value is above its measured start value, or if the segment runs over twice its measured time. The USB cable is held clear of the wheels by the adult. Fingers and hair clear of wheels and discs while the motor battery is on. Lift the rover (wheels in the air) before switching the motor battery back on: the sketch keeps running on USB, so the wheels take its last command at once.

    Works towards: Data-driven tuning, Versions and changes

Materials

  • The encoder rover from R14-U2, with its two wheel controllers (motor battery: 4 × AA alkaline cells (1.5 V each, about 6 V fresh) in a holder whose on/off switch is the power-off switch)
  • A computer with the Arduino IDE (its Serial Monitor and Serial Plotter), a spreadsheet program and a long USB cable for the tether
  • Masking tape for the 2 m line, a tape measure, an incandescent torch (not a halogen lamp), a digital multimeter
  • A notebook page for the version table

⚠ Safety before any session

  • Motors run from their own battery through the driver, never from a pin; every GND is joined.
  • To rewire: switch off and disconnect the motor battery first, then unplug USB. Never move a wire while powered.
  • Wheels lifted for the first run of every new version; then on the floor never above 160 of 255.
  • Every controller's output passes through constrain(…, 0, 160): no gain can drive a wheel above the floor ceiling.
  • Lift the rover (wheels in the air) before switching the motor battery back on: the sketch keeps running on USB, so the wheels take its last command at once.
  • The power-off switch on the motor battery is the stop that always works; STOP on A0 is extra. Test both before every floor run.
  • The stall rule: in every driving state, go to STOPPED if a wheel's count is unchanged for 5 samples while its value is above its measured start value, or if the segment runs over twice its measured time.
  • Fingers and hair clear of wheels and discs while the motor battery is on.
  • The USB cable is held clear of the wheels by the adult.
  • The light test uses an incandescent torch held by the adult, never a hot halogen lamp, kept clear of the wheels and wires.
  • Motor battery: AA alkaline cells only; no NiMH, Li-ion, LiPo, RC packs or 18650 cells.
  • If anything gets warm: switch off or unplug at the holder, don't touch it, tell the adult.

Notes for the adult

  • Version control at this age is practical: dated sketch versions with a change note, never edited once tested. Use git only if the school already has it.
  • One change at a time is the rule that makes a graph mean something: if two settings changed, the data cannot say which one helped.
  • Logs and graphs hold only rover data (times, counts, values): no names or photos of people.
  • Each session lists a line to predict before power-on, a first check when it goes wrong, and a question to reflect on before tidying up.
  • Before the first upload, test an upload on each computer (Blink, with its own board and cable), so the session starts on time.
  • Learners who are ready can start here at any age once they have a working closed-loop controller (R14-U2) and have tuned a setting before (R11-U3).

Planned studio features

Not built yet. The unit runs without them.

  • A log viewer: paste a CSV log from the Serial Monitor and plot it in the browser, kept in the browser only.
  • A sampling view in the wheel-speed P-controller lab: the same run sampled at different intervals.

Sources

The facts this plan relies on, in each source's own words.