Re-Bot
A floor robot that teaches children aged three to seven to program, from six buttons on its back up to drag-and-drop blocks with loops and variables, and stays accurate enough that a wrong answer is always the child’s own.
Context
Re-Bot is a floor robot built for Re-Play in Sweden, for children between roughly three and seven. A child gives it a sequence of moves and it drives that sequence across a mat: forward 150mm, back 150mm, turn ninety degrees, repeat. The point of it is learning to program, and it teaches that on three levels over the same robot. Six large tactile buttons on the robot itself record a sequence and play it back, which is the whole product for a preschooler who cannot yet read. A Flutter application adds a drag-and-drop block editor, Blu’s Blocks, where a child assembles a program visually and watches each block light up as the robot performs it. Above that sit Scratch-style blocks carrying real logic, loops and variables, for a child who has stopped listing moves and started expressing ideas. The same application also drives the robot live in controller mode and manages a classroom full of them at once. The chassis is the third teaching surface: it is modular and meant to be rebuilt by children out of reused craft materials, with the printed structural parts in PLA, so the robot teaches sequencing, spatial reasoning and something about reuse by being taken apart rather than by being told.
The problem
The hard requirement is accuracy, and the reason is pedagogical rather than technical. These robots run on a printed grid, and a child chains ten or twenty commands before pressing GO. If each 150mm step is a few millimetres out and each turn a couple of degrees off, the errors compound and the robot finishes in the wrong square. A five-year-old does not conclude that the wheels slipped. They conclude that they got it wrong, and the lesson has taught the opposite of what it was for. So the robot has to be a truthful executor of a child’s program, which sets a tolerance of plus or minus eight millimetres and four degrees on hardware driven by a battery that sags, wheels that wear and floors that differ from one classroom to the next. Everything else follows from that: no server to check against, no adult debugging in the moment, and forty-five minutes of a lesson in which it either works or the class is spent.
The solution
Closed-loop movement rather than timed movement, which is the difference between usually roughly right and reproducibly right. Hall-effect encoders on the geared motors are counted in interrupt handlers so no pulse is missed, and a wheel-diameter and pulses-per-revolution calculation converts ticks into millimetres, so the robot drives until it has actually travelled 150mm rather than for however long that usually takes. Turns are held by the MPU6050 instead, integrating angular velocity on the Z axis until the heading reaches target. Calibration offsets live in flash rather than memory, because a classroom robot is switched off every day and a calibration that does not survive that is worthless. Every one of those programming surfaces feeds one command queue of up to two hundred steps, with a physical toggle deciding whether the keypad or the application is in charge, and the application tracks progress through a program block by block as the robot confirms each move. An infrared sensor sits above all of it: the main loop checks it every pass, and an obstacle during a forward move brakes the motors and tells the application, because the thing in the way is usually a child.
Architecture
A phone and a microcontroller over Bluetooth Low Energy, and no server behind either of them. The Flutter application is built on flutter_bloc with cubits for Bluetooth and application state, and talks to the robot over a serial-style BLE characteristic. Commands go down as short strings and the robot notifies back: DONE when a movement completes, OBSTACLE when the infrared sensor stops one. That return path is what makes block programming honest, because the application cannot advance the highlighted block until the physical world has confirmed the last one. On the robot an ESP32 runs C and C++ firmware across a custom board: two PWM channels and four direction pins into a TB6612FNG driving the geared motors, four encoder pins read by interrupt service routines, I2C to the MPU6050, six GPIO for the keypad, and one pin each for the buzzer and an addressable WS2812B carrying status colour through FastLED. The main loop does three things at once: scan the keypad, watch the encoder count against its target, and keep integrating heading. Not built yet, and specified rather than shipped: over-the-air updates, PID on the motor loop, forty-five degree turns, voice control and robot-to-robot interaction.
Read this diagram as text
- Flutter app
- Flutter with flutter_bloc and cubits. Three ways in: live driving in controller mode, drag-and-drop programming in Blu’s Blocks, and Scratch-style blocks carrying logic, loops and variables. Plus a multi-bot manager that renames, colour-tags and groups the robots in a classroom.
- On-robot keypad
- Six large tactile buttons: four directions, GO and CLEAR. The first rung of the ladder rather than a fallback, and the whole product for a child too young to read a screen.
- Encoders & MPU6050
- Closed-loop feedback. Hall-effect encoders counted in interrupt handlers convert pulses to millimetres for a 150mm step; the MPU6050 integrates Z-axis angular velocity for a turn that stops at 88.5 degrees because momentum carries the rest.
- IR obstacle sensor
- Checked every pass of the main loop and allowed to override the command in progress, because the obstacle in a classroom is usually a child.
- Custom PCB & PLA chassis
- A board built for this robot, inside a 3D-printed PLA structure with integrated motor cages, and an outer body children rebuild from reused craft materials.
- BLE link
- A serial-style characteristic and the entire distance between the two halves of the product. Short commands down, DONE and OBSTACLE notifications back.
- ESP32 · C/C++ firmware
- One image doing three things at once: scanning the keypad, watching encoder counts against target, and integrating heading, while servicing the radio and never stalling any of them.
- TB6612FNG & geared motors
- Differential drive through an H-bridge on two PWM channels, with a ball caster for the third point of contact so a turn can pivot on the spot.
- WS2812B & buzzer
- Colour and tone for ready, running, finished, obstacle and low battery. With no server behind the product, this is the entire diagnostic interface a teacher has.
- Queue & calibration
- Up to two hundred command steps, and the calibration offsets that keep the robot inside tolerance. Held in flash because a classroom robot is switched off every day.
- Flutter app → BLE link (commands, DONE, OBSTACLE)
- BLE link → ESP32 · C/C++ firmware (the wireless surface)
- On-robot keypad → ESP32 · C/C++ firmware (record and play)
- Encoders & MPU6050 → ESP32 · C/C++ firmware (ticks and degrees)
- IR obstacle sensor → ESP32 · C/C++ firmware (overrides the move in progress)
- Custom PCB & PLA chassis → ESP32 · C/C++ firmware (carries)
- ESP32 · C/C++ firmware → TB6612FNG & geared motors (PWM and direction)
- ESP32 · C/C++ firmware → WS2812B & buzzer (colour and tone)
- ESP32 · C/C++ firmware → Queue & calibration (200 steps, calibration offsets)
What makes it interesting
The parts a system like this is actually judged on.
- Accuracy here is a pedagogical requirement, not an engineering vanity. The robot runs on a printed grid and a child chains commands before pressing GO, so error compounds across the sequence. Land in the wrong square and a five-year-old concludes their thinking was wrong rather than that the wheels slipped, which teaches the exact opposite of the lesson. The eight-millimetre and four-degree tolerances exist to protect a child’s reasoning from the hardware, and every decision underneath them is downstream of that.
- Closed loop instead of timed, which is what makes a two-hundred-step sequence survivable. A simpler floor robot drives forward for a fixed duration and is usually roughly right; the error is unbounded and compounds every step. Counting encoder pulses to a distance and integrating gyro angle to a heading bounds the error per command instead, so twenty commands are not twenty times worse than one. That is the whole reason for the encoders and the IMU, and it is a scheduling problem too, because the pulses arrive whether or not the main loop is busy, which is why they are counted in interrupt handlers rather than polled.
- The turn constant is 88.5 degrees rather than 90, and that number cannot be derived. The robot is asked for a right angle and told to stop one and a half degrees early, because momentum and floor friction carry it the rest of the way. The gyro integration carries a similar empirical scale factor. These are the physical world appearing in the source as magic numbers that were measured rather than calculated, and they are the part of embedded work that does not survive being moved to a different floor without being measured again.
- The same robot has to be programmable by a three-year-old and by a seven-year-old, which is a problem of abstraction rather than of features. There are three levels over one command queue: six tactile buttons for a child who cannot read, a drag-and-drop block editor for one who can sequence but not yet generalise, and Scratch-style blocks with logic, loops and variables for one who can. The hardware never changes and neither does the queue underneath. What changes is how much of a program the child is allowed to say, so the learning ladder is a product decision expressed as three front-ends onto one interpreter, and a class can run all three at once on identical robots.
- Loops are where a child stops describing and starts programming, which makes the loop block the pedagogical centre of the whole application. Forward, forward, forward is a list of moves; repeat this three times is an idea about moves, and it is the first point at which a program says something the child has not written out longhand. It is also what makes the two-hundred-step queue matter, because a loop is compact on screen and expands into the queue, so the limit a child can actually hit is reached by thinking well rather than by typing a lot.
- Calibration has to outlive the power switch, which is why it is in flash. Wheels wear, batteries sag between charges, and a carpeted classroom is not a hall floor, so the offsets that keep the robot inside tolerance are specific to that robot on that day. A calibration held in memory is gone by the next lesson, and a teacher will not recalibrate twelve robots every morning. Persisting it is marked imperative in the specification, and that is the correct weight.
- The infrared sensor outranks everything else in the loop, deliberately. Obstacle detection is checked every pass and, during a forward move, overrides the command in progress: brake, signal, notify. This is a priority inversion chosen on purpose, because the obstacle in a room of small children is usually a small child, and a robot that finishes its instruction first has failed at something more important than the instruction.
- Sustainability is in the chassis rather than in a lesson slide. The body is modular and meant to be rebuilt by children from reused craft materials, with the printed structure in PLA, so the environmental idea is taught by the object being taken apart and remade rather than by being described. It also puts a real constraint on the mechanical design, because a structure children reassemble has to keep motor alignment and a low centre of gravity while tolerating being rebuilt badly.
- There is no server anywhere in the product, and that shapes what can be known. No backend, no telemetry, no remote configuration, no path to ship a fix to a robot in a Swedish classroom. Everything normally observable at runtime has to be designed in beforehand or done without, which is why the status LED and the buzzer are not decoration: colour and tone are the entire diagnostic interface a teacher has.
Engineering challenges
- Plus or minus eight millimetres and four degrees, on battery-driven hardware across classroom floors that differ
- Compounding error across a two-hundred-command sequence, which closed-loop feedback bounds and timed movement does not
- Constants that must be measured rather than derived, like a 90-degree turn that stops at 88.5
- Three levels of programming abstraction, from six buttons to blocks to loops and variables, over one command queue
- A block editor that must stay in step with a robot in the physical world, block by block
- Calibration that has to survive a power cycle, because nobody recalibrates twelve robots each morning
- An obstacle check that must outrank the command in progress, in a room of small children
- A chassis children rebuild from reused materials that still has to hold motor alignment
- No server anywhere: an LED and a buzzer are the whole diagnostic surface
Integrations
- Bluetooth Low Energy: a serial-style characteristic carrying short commands to the robot and DONE or OBSTACLE notifications back, which is what lets the application track physical progress through a program
Technology
- Flutter
- Dart
- flutter_bloc
- Bluetooth Low Energy
- ESP32
- C/C++
- MPU6050
- Hall-effect encoders
- TB6612FNG
- DC geared motors
- FastLED
- WS2812B
- Custom PCB
- 3D printing (PLA)
- Docker