🤖 Level 4 – Mobile Robotics

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

PartHow many?Pin connection (R32)
D1 R321USB cable
L298N motor driver1ENA → 5 (PWM), ENB → 18 (PWM), IN1 → 23, IN2 → 19, IN3 → 13, IN4 → 21
Caterpillar tracks + motors2Connect to L298N outputs
Bluetooth (built‑in)1Internal
Power supply17–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
On this page