Project 4.1: "Bluetooth-Controlled Caterpillar Robot"
What you’ll learn
- Goal 1: Move caterpillar tracks forward and backward with motor driver.
- Goal 2: Perform tracked turns (left/right).
- Goal 3: Control track speed with PWM.
- Goal 4: Receive basic Bluetooth commands and apply them to movement.
- Goal 5: Execute complex movement patterns (zig‑zag, patrol).
Key ideas
- Motor driver: L298N channels drive left and right tracks.
- PWM: Adjust duty cycle for speed control.
- Bluetooth: Commands from PC or phone control robot.
- Integration: Combine movement primitives into patterns.
Blocks glossary
- PWM output: Controls motor speed (ENA/ENB).
- Digital output: Sets motor direction pins (IN1–IN4).
- Bluetooth peripheral: Receives text commands from PC/phone.
- Callback (receive): Function triggered when Bluetooth message arrives.
- Serial print: Logs actions for debugging.
- def function: Helpers for forward(), backward(), turn_left(), turn_right(), stop().
- Loop: Waits for Bluetooth commands and executes actions.
What you need
| Part | How many? | Pin connection (R32) |
|---|---|---|
| D1 R32 | 1 | USB cable |
| L298N motor driver | 1 | ENA → 5 (PWM), ENB → 18 (PWM), IN1 → 23, IN2 → 19, IN3 → 13, IN4 → 21 |
| Caterpillar tracks + motors | 2 | Connect to L298N outputs |
| Bluetooth (built‑in) | 1 | Internal |
| Power supply | 1 | 7–12 V for motors |
Before you start
- Connect USB and open serial monitor.
- Quick test:
print("Ready!") # Confirm serial is working
🎮 Microprojects (5 mini missions)
🎮 Microproject 4.1.1 – Caterpillar movement forward/backward
# Microproject 4.1.1 – Forward and backward movement
import machine # Load hardware pin/PWM library
import time # Load time library
# Setup PWM pins for motor speed control
pwmA = machine.PWM(machine.Pin(5)) # ENA pin for left track
pwmB = machine.PWM(machine.Pin(18)) # ENB pin for right track
pwmA.freq(2000) # Set PWM frequency to 2kHz
pwmB.freq(2000) # Set PWM frequency to 2kHz
# Setup digital pins for motor direction
in1 = machine.Pin(23, machine.Pin.OUT) # IN1 for left motor direction
in2 = machine.Pin(19, machine.Pin.OUT) # IN2 for left motor direction
in3 = machine.Pin(13, machine.Pin.OUT) # IN3 for right motor direction
in4 = machine.Pin(21, machine.Pin.OUT) # IN4 for right motor direction
def forward(): # Helper: move forward
in1.value(1) # Left motor forward
in2.value(0) # Left motor not backward
in3.value(1) # Right motor forward
in4.value(0) # Right motor not backward
pwmA.duty(650) # Medium speed left
pwmB.duty(650) # Medium speed right
print("[Robot] Forward") # Serial: log action
def backward(): # Helper: move backward
in1.value(0) # Left motor not forward
in2.value(1) # Left motor backward
in3.value(0) # Right motor not forward
in4.value(1) # Right motor backward
pwmA.duty(650) # Medium speed left
pwmB.duty(650) # Medium speed right
print("[Robot] Backward") # Serial: log action
forward() # Test forward
time.sleep_ms(1000) # Run for 1 second
backward() # Test backward
time.sleep_ms(1000) # Run for 1 second
🎮 Microproject 4.1.2 – Tracked turns
# Microproject 4.1.2 – Left and right turns
def turn_left(): # Helper: turn left
in1.value(0) # Left motor backward
in2.value(1) # Left motor backward
in3.value(1) # Right motor forward
in4.value(0) # Right motor forward
pwmA.duty(650) # Medium speed left
pwmB.duty(650) # Medium speed right
print("[Robot] Turn left") # Serial: log action
def turn_right(): # Helper: turn right
in1.value(1) # Left motor forward
in2.value(0) # Left motor forward
in3.value(0) # Right motor backward
in4.value(1) # Right motor backward
pwmA.duty(650) # Medium speed left
pwmB.duty(650) # Medium speed right
print("[Robot] Turn right") # Serial: log action
turn_left() # Test left turn
time.sleep_ms(1000) # Run for 1 second
turn_right() # Test right turn
time.sleep_ms(1000) # Run for 1 second
🎮 Microproject 4.1.3 – Track speed control
# Microproject 4.1.3 – Speed control with PWM
def set_speed(val): # Helper: set speed duty
pwmA.duty(val) # Apply duty to left motor
pwmB.duty(val) # Apply duty to right motor
print("[Robot] Speed set:", val) # Serial: log speed
set_speed(400) # Test slow speed
forward() # Move forward slowly
time.sleep_ms(1000) # Run for 1 second
set_speed(900) # Test fast speed
forward() # Move forward fast
time.sleep_ms(1000) # Run for 1 second
🎮 Microproject 4.1.4 – Basic Bluetooth control
# Microproject 4.1.4 – Bluetooth commands to control movement
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback helper
ble_p = ble_peripheral.BLESimplePeripheral('Caterpillar-R32') # Peripheral named 'Caterpillar-R32'
print("[Robot] BLE 'Caterpillar-R32' ready") # Serial: confirm BT init
handle = ble_handle.Handle() # Callback handle
print("[Robot] BT handle ready") # Serial: confirm handle
def handle_method(msg): # Callback: process BT commands
s = str(msg) # Ensure string type
print("[Robot] BT RX:", s) # Serial: log incoming
if s == "FWD": # Forward command
forward() # Call forward helper
ble_p.send("ACK:FWD") # Send ACK to PC
elif s == "BACK": # Backward command
backward() # Call backward helper
ble_p.send("ACK:BACK") # Send ACK to PC
elif s == "LEFT": # Left turn command
turn_left() # Call left turn helper
ble_p.send("ACK:LEFT") # Send ACK to PC
elif s == "RIGHT": # Right turn command
turn_right() # Call right turn helper
ble_p.send("ACK:RIGHT") # Send ACK to PC
elif s.startswith("SPD:"): # Speed command
val = int(s.split(":")[1]) # Parse speed value
set_speed(val) # Apply speed
ble_p.send("ACK:SPD=" + str(val)) # Send ACK to PC
else: # Unknown command
ble_p.send("ERR:UNKNOWN") # Send error feedback
handle.recv(handle_method) # Register callback
print("[Robot] Callback registered") # Serial: callback active
while True: # Idle loop; actions via callback
time.sleep_ms(150) # Keep CPU cool
🧭 Clu‑Bots Tutorial Template for Self‑Taught Learners (Ages 11–18)
Level 4 – Project 4.1: “Bluetooth‑Controlled Caterpillar Robot”
(Continuación y finalización desde donde nos quedamos)
🎮 Microproject 4.1.5 – Complex movement patterns (zig‑zag patrol)
# Microproject 4.1.5 – Complex movement patterns (zig-zag patrol)
import time # Load time library for delays
def zigzag(): # Helper: zig-zag movement pattern
forward() # Step 1: move forward
time.sleep_ms(800) # Run forward for 0.8 seconds
turn_left() # Step 2: turn left
time.sleep_ms(400) # Short left turn for 0.4 seconds
forward() # Step 3: move forward again
time.sleep_ms(800) # Run forward for 0.8 seconds
turn_right() # Step 4: turn right
time.sleep_ms(400) # Short right turn for 0.4 seconds
forward() # Step 5: move forward again
time.sleep_ms(800) # Run forward for 0.8 seconds
stop() # Step 6: stop robot
print("[Robot] Zigzag pattern complete") # Serial: log completion
def stop(): # Helper: stop robot
pwmA.duty(0) # Set left motor duty to 0
pwmB.duty(0) # Set right motor duty to 0
print("[Robot] Stop") # Serial: log stop action
# Test zigzag pattern
zigzag() # Execute zigzag patrol once
Reflection: Combining primitives into a pattern makes the robot feel alive.
Challenge: Add a “patrol loop” that repeats zigzag 3 times.
✨ Main Project – Bluetooth‑Controlled Caterpillar Robot
# Project 4.1 – Bluetooth-Controlled Caterpillar Robot
# Full integration: forward/backward, turns, speed control, Bluetooth commands, complex patterns.
import machine # Load hardware pin/PWM library
import time # Load time library
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback helper
# Setup PWM pins for motor speed control
pwmA = machine.PWM(machine.Pin(5)) # ENA pin for left track
pwmB = machine.PWM(machine.Pin(18)) # ENB pin for right track
pwmA.freq(2000) # Set PWM frequency to 2kHz
pwmB.freq(2000) # Set PWM frequency to 2kHz
# Setup digital pins for motor direction
in1 = machine.Pin(23, machine.Pin.OUT) # IN1 for left motor direction
in2 = machine.Pin(19, machine.Pin.OUT) # IN2 for left motor direction
in3 = machine.Pin(13, machine.Pin.OUT) # IN3 for right motor direction
in4 = machine.Pin(21, machine.Pin.OUT) # IN4 for right motor direction
# Bluetooth setup
ble_p = ble_peripheral.BLESimplePeripheral('Caterpillar-R32') # Peripheral named 'Caterpillar-R32'
print("[Robot] BLE 'Caterpillar-R32' ready") # Serial: confirm BT init
handle = ble_handle.Handle() # Callback handle
print("[Robot] BT handle ready") # Serial: confirm handle
# Movement helpers
def forward():
in1.value(1); in2.value(0) # Left motor forward
in3.value(1); in4.value(0) # Right motor forward
pwmA.duty(650); pwmB.duty(650) # Medium speed both
print("[Robot] Forward") # Serial: log action
def backward():
in1.value(0); in2.value(1) # Left motor backward
in3.value(0); in4.value(1) # Right motor backward
pwmA.duty(650); pwmB.duty(650) # Medium speed both
print("[Robot] Backward") # Serial: log action
def turn_left():
in1.value(0); in2.value(1) # Left motor backward
in3.value(1); in4.value(0) # Right motor forward
pwmA.duty(650); pwmB.duty(650) # Medium speed both
print("[Robot] Turn left") # Serial: log action
def turn_right():
in1.value(1); in2.value(0) # Left motor forward
in3.value(0); in4.value(1) # Right motor backward
pwmA.duty(650); pwmB.duty(650) # Medium speed both
print("[Robot] Turn right") # Serial: log action
def stop():
pwmA.duty(0); pwmB.duty(0) # Stop both motors
print("[Robot] Stop") # Serial: log action
def set_speed(val):
pwmA.duty(val); pwmB.duty(val) # Apply duty to both motors
print("[Robot] Speed set:", val) # Serial: log speed
def zigzag():
forward(); time.sleep_ms(800) # Forward
turn_left(); time.sleep_ms(400) # Left turn
forward(); time.sleep_ms(800) # Forward
turn_right(); time.sleep_ms(400) # Right turn
forward(); time.sleep_ms(800) # Forward
stop() # Stop
print("[Robot] Zigzag pattern complete") # Serial: log completion
# Bluetooth callback
def handle_method(msg):
s = str(msg) # Ensure string type
print("[Robot] BT RX:", s) # Serial: log incoming
if s == "FWD":
forward(); ble_p.send("ACK:FWD") # Execute forward + ACK
elif s == "BACK":
backward(); ble_p.send("ACK:BACK") # Execute backward + ACK
elif s == "LEFT":
turn_left(); ble_p.send("ACK:LEFT") # Execute left turn + ACK
elif s == "RIGHT":
turn_right(); ble_p.send("ACK:RIGHT") # Execute right turn + ACK
elif s == "STOP":
stop(); ble_p.send("ACK:STOP") # Execute stop + ACK
elif s.startswith("SPD:"):
val = int(s.split(":")[1]) # Parse speed value
set_speed(val); ble_p.send("ACK:SPD=" + str(val)) # Apply speed + ACK
elif s == "PATTERN:ZIGZAG":
zigzag(); ble_p.send("ACK:ZIGZAG") # Execute zigzag + ACK
else:
ble_p.send("ERR:UNKNOWN") # Error feedback
handle.recv(handle_method) # Register callback
print("[Robot] Callback registered") # Serial: callback active
while True: # Idle loop; actions via callback
time.sleep_ms(150) # Keep CPU cool
External explanation
This project integrates motor driver control with Bluetooth commands. Students learn to send commands from a PC or phone, receive them on the robot, and execute precise movements. The robot acknowledges each command back to the PC via Bluetooth, ensuring clarity and reducing frustration.
Story time
Your caterpillar robot listens to your phone. You say “FWD,” it crawls forward. You say “PATTERN:ZIGZAG,” it patrols like a little tank. Every move is confirmed back to you — no surprises, just teamwork.
Debugging (2)
Debugging 4.1.A – Caterpillars become misaligned
- Symptom: Robot veers off course.
- Fix: Adjust duty values separately for left and right motors.
pwmA.duty(640) # Slightly lower left speed
pwmB.duty(650) # Keep right speed
Debugging 4.1.B – Slow Bluetooth response
- Symptom: Commands feel delayed.
- Fix: Reduce loop delays and keep messages short.
time.sleep_ms(80) # Shorter idle delay for faster callback response
ble_p.send("ACK:FWD") # Keep ACK concise
Final checklist
- Forward/backward helpers work.
- Left/right turns are correct.
- Speed control adjusts smoothly.
- Bluetooth commands trigger actions and send ACKs.
- Zigzag pattern executes and confirms.
Extras
- Student tip: Try sending commands from a PC terminal via Bluetooth and watch ACKs return.
- Instructor tip: Encourage students to tweak duty values to calibrate straight movement.
- Glossary:
- PWM duty: Percentage of ON time controlling motor speed.
- ACK: A short confirmation message sent back to the sender.
- Pattern: A sequence of primitive moves forming a behavior.
- Mini tips:
- Always debounce buttons if used for manual control.
- Keep Bluetooth messages short (FWD, BACK, LEFT, RIGHT, STOP, SPD:xxx).
- Celebrate when