Build a simple two-wheeled robot controlled by OctoMY™. This tutorial walks through hardware assembly, wiring, and basic control.
Pro Tip
Don't have all the parts? Start with a robot kit! 2WD Smart Car Kits are inexpensive and include chassis, motors, wheels, and often a motor driver - everything you need except the Arduino and phone.
A differential-drive robot that:
┌───────────────────┐
│ Android Phone │
│ (Agent brain) │
└─────────┬─────────┘
│ USB
┌─────────┴─────────┐
│ Arduino + ArduMY │
└────┬─────────┬────┘
│ │
┌────┴───┐ ┌───┴────┐
│ Motor │ │ Motor │
│ Left │ │ Right │
└────────┘ └────────┘
| Component | Quantity | Notes |
|---|---|---|
| Android phone | 1 | Android 8+ |
| Arduino Mega/Uno | 1 | Mega recommended |
| Motor driver (L298N) | 1 | Dual H-bridge |
| DC geared motors | 2 | 6V, with encoders optional |
| Wheels | 2 | Matched to motors |
| Caster wheel | 1 | For stability |
| USB OTG cable | 1 | Phone to Arduino |
| Battery pack | 1 | 6-12V for motors |
| Power bank | 1 | For phone (optional) |
| Chassis | 1 | Acrylic, 3D printed, or kit |
Did You Know?
The L298N motor driver can handle up to 2A per channel and 12V motors. For larger robots with more powerful motors, consider the BTS7960 driver which handles 43A!
Many robot chassis kits are available:
Print a simple base plate with motor mounts:
┌─────────────────────────────┐
│ ○ ○ │ ← Mounting holes
│ │
│ [Motor] [Motor] │ ← Motor mounts
│ ○ ○ │
│ │
│ [Caster] │ ← Rear caster
│ ○ │
└─────────────────────────────┘
Cut a simple rectangular base (15x20 cm works well).
Mount the caster wheel at the rear center:
[Left Motor]═════════════════[Right Motor]
│ │
▼ ▼
(Wheel) [Chassis] (Wheel)
│
(Caster)
L298N Motor Driver
┌─────────────────────────────────────────────┐
│ │
│ [12V+] [GND] [5V] Motor power input │
│ │
│ [ENA] [IN1] [IN2] [IN3] [IN4] [ENB] │
│ │
│ [OUT1] [OUT2] [OUT3] [OUT4] │
│ └──Motor A──┘ └──Motor B──┘ │
└─────────────────────────────────────────────┘
| L298N Pin | Connect To |
|---|---|
| 12V+ | Battery positive |
| GND | Battery negative + Arduino GND |
| 5V | Arduino 5V (or leave as output) |
| ENA | Arduino D9 (PWM) |
| IN1 | Arduino D8 |
| IN2 | Arduino D7 |
| IN3 | Arduino D6 |
| IN4 | Arduino D5 |
| ENB | Arduino D10 (PWM) |
| OUT1/OUT2 | Left motor |
| OUT3/OUT4 | Right motor |
Security Consideration
Always use a separate power source for motors (not USB power). Motor noise can cause Arduino resets and unpredictable behavior. Keep motor power wires away from signal wires.
Open Arduino IDE
Open the ArduMY sketch from OctoMY™ source:
src/libs/libardumy/arduino/ArduMYMain.ino
Configure for your motors:
// Motor A (Left)
#define MOTOR_A_EN 9
#define MOTOR_A_IN1 8
#define MOTOR_A_IN2 7
// Motor B (Right)
#define MOTOR_B_EN 10
#define MOTOR_B_IN1 6
#define MOTOR_B_IN2 5
Upload to Arduino
Open Serial Monitor at 115200 baud. You should see:
ArduMY v1.0 ready
Actuators: 2
Waiting for commands...
┌─────────────────────────────────────────────┐
│ Controller Status │
├─────────────────────────────────────────────┤
│ │
│ Device: Arduino Mega │
│ Status: ● Connected │
│ Actuators: 2 (motors.left, motors.right) │
│ │
│ [Configure] [Test] │
│ │
└─────────────────────────────────────────────┘
Pro Tip
Not all USB OTG cables are created equal. If your phone doesn't detect the Arduino, try a different cable. Some cheap cables only support charging, not data.
┌─────────────────────────────────────────────┐
│ Configure Actuator │
├─────────────────────────────────────────────┤
│ │
│ Name: motors.left │
│ Type: DC Motor │
│ Control: PWM + Direction │
│ │
│ PWM Pin: 9 │
│ Dir Pin 1: 8 │
│ Dir Pin 2: 7 │
│ │
│ [Test Motor] [Save] │
│ │
└─────────────────────────────────────────────┘
Use the Test Motor button to verify:
┌─────────────────────────────────────────────┐
│ Pairing Complete │
├─────────────────────────────────────────────┤
│ │
│ Thundering Walrus (Remote) │
│ paired with │
│ Gentle Badger (Agent) │
│ │
│ Trust Level: [████████░░] Handshake │
│ │
│ [View Agent] [Done] │
│ │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ Control: Gentle Badger │
├─────────────────────────────────────────────┤
│ │
│ ┌───────────────┐ │
│ │ ▲ │ │
│ │ ◄ ● ► │ Speed: 60% │
│ │ ▼ │ │
│ └───────────────┘ │
│ Joystick │
│ │
│ Mode: [Joystick ▼] [STOP] │
│ │
└─────────────────────────────────────────────┘
The canonical control surface for any robot exposing intent:ground-drive-2d is the Ground Drive activity in Remote. It maps the joystick to forward / yaw and surfaces any optional ports (parking brake, horn, etc.) in an auto-rendered bank below.
| Mode | Description |
|---|---|
| Ground Drive | Joystick → intent:ground-drive-2d.forward / .yaw; works against any consuming lobe (differential_drive, legged_gait_2d) |
| Scenes | Apply a pre-authored multi-channel snapshot; see Author scenes |
| Stanzas | Generic per-channel stanza picker — falls back to a slider bank when no purpose-built widget matches |
If the robot veers left or right:
For safety during testing:
| Issue | Solution |
|---|---|
| No power to motors | Check battery connections |
| Motors jitter but don't spin | Battery too weak, use higher voltage |
| Arduino not detected | Try different USB cable/port |
| Only one motor works | Check motor driver wiring |
| Issue | Solution |
|---|---|
| Sudden direction changes | Check for loose connections |
| Intermittent stops | Battery running low |
| Opposite direction | Swap IN1/IN2 in configuration |
| Issue | Solution |
|---|---|
| Remote can't find Agent | Check both on same network |
| Pairing fails | Restart both apps, try again |
| High latency | Move closer, reduce interference |
Now that your basic robot works: