Project 5.1: "Mobile App to Control Robot"
What youâll learn
- â App control: Use a simple phone app to send commands to the D1 R32 over Bluetooth.
- â Robot moves: Make the robot respond to âFWD / BACK / LEFT / RIGHT / STOPâ.
- â Customization: Change command names and add your own buttons or actions.
Key ideas
- Short definition: Bluetooth lets two devices talk wirelessly using short text messages.
- Real-world link: Remote controls, gamepads, and smart home apps use similar wireless messages.
Blocks glossary (used in this project)
- Bluetooth init (central/peripheral): Starts Bluetooth so devices can find and talk to each other.
- Scan / connect: Central device looks for a peripheral by name and connects.
- Receive message callback: Runs a function every time a message arrives.
- Serial println: Shows status messages on your computer to confirm behavior.
- Variable: Stores the last command or a status like âconnectedâ.
What you need
| Part | How many? | Pin connection |
|---|---|---|
| D1 R32 | 1 | USB cable (30 cm) |
| Smartphone (Android/iOS) | 1 | Bluetooth enabled |
đ Wiring tip: No extra wiring needed for this project. Just plug in USB and enable Bluetooth on your phone.
đ Pin map snapshot: All pins remain free; movement commands are simulated. You can map them to motors later (e.g., L298N).
Before you start
- USB cable is plugged in
- Serial monitor is open
- Test print shows:
print("Ready!") # Confirm serial is working
Microprojects (5 mini missions)
Microproject 5.1.1 â Basic app interface design
Goal: Prepare a simple app UI with buttons: FWD, BACK, LEFT, RIGHT, STOP.
Blocks used:
- Serial println: Show âWaiting for appâŠâ
- Variable: Store last_command for testing.
Block sequence:
- Initialize a variable last_command = “NONE”.
- Print âOpen the app and press a buttonâ.
- Simulate sending commands from app later.
MicroPython code:
last_command = "NONE" # Save the last app command received
print("Microproject 5.1.1: Waiting for app...") # Tell the student what to do
print("Create app buttons: FWD, BACK, LEFT, RIGHT, STOP") # UI plan reminder
print("Press buttons to send words like 'FWD'") # Define expected messages
Reflection: A good UI is simple and clearâlabels should match robot actions.
Challenge:
- Easy: Add a âSTOPâ button in a different color.
- Harder: Add a âSLOWâ and âFASTâ toggle button.
Microproject 5.1.2 â Connecting the app to R32
Goal: Start Bluetooth and connect.
Blocks used:
- Init central/peripheral: Start both roles.
- Scan / connect by name: Connect to âClu-Botsâ.
- Serial println: Show connection status.
Block sequence:
- Init central (host) and peripheral (name âClu-Botsâ).
- Scan for devices.
- Connect to name âClu-Botsâ.
- Print âConnected!â on success.
MicroPython code:
import ble_central # Import Bluetooth central role library
import ble_peripheral # Import Bluetooth peripheral role library
import ble_handle # Import message handling helper
ble_c = ble_central.BLESimpleCentral() # Create central to scan/connect
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral named 'Clu-Bots'
print("Microproject 5.1.2: Starting Bluetooth...") # Status message
ble_c.scan() # Begin scanning for peripherals
print("Scanning for 'Clu-Bots'...") # Tell student what we look for
ble_c.connect(name='Clu-Bots') # Try connecting to the peripheral by name
print("If connected, you should see 'Connected!' in the app") # Explain expected result
Reflection: Two roles help us test locally: phone connects to âClu-Bots,â and central role simulates device discovery.
Challenge:
- Easy: Change the peripheral name to âClu-Bots-5â.
- Harder: Show the local MAC address (if available) as feedback.
Microproject 5.1.3 â Directional control from the app
Goal: Receive app messages and update last_command.
Blocks used:
- Receive message callback: Calls a function when data arrives.
- Serial println: Show the received text.
Block sequence:
- Define handle_method(key1, key2, key3, keyx).
- In the function, print the message.
- Save message to last_command.
- Attach the callback.
MicroPython code:
last_command = "NONE" # Track the most recent app command
def handle_method(key1, key2, key3, keyx): # Define callback with required parameters
msg = str(key1) # Convert first field to text (the app sends main content in key1)
print("Received from app:", msg) # Show the message on serial for confirmation
global last_command # We will modify the global variable
last_command = msg # Save the last command
print("last_command set to:", last_command) # Confirm update
handle = ble_handle.Handle() # Create a handle manager for callbacks
handle.recv(handle_method) # Register our callback so it triggers on message receipt
print("Microproject 5.1.3: Callback attached. Send 'FWD', 'LEFT', etc.") # Guidance
Reflection: Callbacks are like doorbellsâthe function runs as soon as a message arrives.
Challenge:
- Easy: Print âUnknown commandâ if message isnât one of the 5 choices.
- Harder: Add a timestamp using system running time when a command arrives.
Microproject 5.1.4 â Sending sensor data to the app
Goal: Return a simple status string to the app.
Blocks used:
- Serial println: Show what weâre sending.
- For app sending, youâll mirror this on the app; here we prepare the message format.
Block sequence:
- Create a status string like âSTATUS:OKâ.
- Print it to serial (students will read this and send back via app UI).
- Plan to send âBAT:100â or âTEMP:25â in future.
MicroPython code:
status_text = "STATUS:OK" # Prepare a simple status message for the app
print("Microproject 5.1.4: Send to app ->", status_text) # Show what should be sent
print("Tip: Map this to an app 'Status' label") # UI guidance for students
Reflection: Clear formats (like âKEY:VALUEâ) make apps easy to parse.
Challenge:
- Easy: Change to âSTATUS:READYâ.
- Harder: Add âMODE:AUTOâ or âMODE:MANUALâ messages.
Microproject 5.1.5 â Customized app interface
Goal: Let students rename buttons and define their own command words.
Blocks used:
- Variable: Store custom labels.
- Serial println: Display chosen labels.
Block sequence:
- Set variables for custom names.
- Print them so students see the current mapping.
- Ask students to match app buttons to the new words.
MicroPython code:
btn_fwd = "FWD" # Custom word for forward
btn_back = "BACK" # Custom word for backward
btn_left = "LEFT" # Custom word for left
btn_right = "RIGHT" # Custom word for right
btn_stop = "STOP" # Custom word for stop
print("Microproject 5.1.5: Button labels ->", btn_fwd, btn_back, btn_left, btn_right, btn_stop) # Show labels
print("Match your app buttons to these exact words") # Instruction to avoid mismatch
Reflection: Consistency avoids bugsâlabels in the app must match labels in code.
Challenge:
- Easy: Add âSPINâ as a new action word.
- Harder: Add âSLOWâ and âFASTâ to change speed modes later.
Main project â Mobile app to control robot
Blocks steps (with glossary)
- Init peripheral âClu-Botsâ: Makes the R32 discoverable by your phone.
- Init central + scan + connect: Confirms discovery flow works in class.
- Receive message callback: Updates last_command when the app sends a word.
- Serial println: Shows connection and command results.
Block sequence:
- Init BLE peripheral named âClu-Botsâ â app can connect.
- Init BLE central â scan â connect by name âClu-Botsâ â verify.
- Register receive-message callback â handle_method prints and stores commands.
- In a loop, check last_command and print simulated actions (map later to motors).
MicroPython code (mirroring blocks)
# Project 5.1 â Mobile App to Control Robot
import ble_central # Import Bluetooth central role for scanning/connecting
import ble_peripheral # Import Bluetooth peripheral role to advertise a name
import ble_handle # Import handler to manage receive callbacks
import time # Import time to add small delays and readable timing
ble_c = ble_central.BLESimpleCentral() # Create central controller
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral named 'Clu-Bots'
print("Bluetooth: Peripheral 'Clu-Bots' ready") # Status: advertising started
ble_c.scan() # Start scanning for peripherals
print("Central: scanning for 'Clu-Bots'...") # Tell the student what is happening
ble_c.connect(name='Clu-Bots') # Attempt to connect to our peripheral
print("Central: connect requested to 'Clu-Bots'") # Connection request status
last_command = "NONE" # Track last app command for control decisions
print("Initial last_command:", last_command) # Confirm initial state
def handle_method(key1, key2, key3, keyx): # Define the message callback function
msg = str(key1) # Convert the main field to a text command
print("Received from app:", msg) # Show the incoming command on serial
global last_command # We will update the global variable
last_command = msg # Save the most recent command
print("last_command updated to:", last_command) # Confirm the update
handle = ble_handle.Handle() # Create a handler manager instance
handle.recv(handle_method) # Attach the callback to run when messages arrive
print("Callback attached: send FWD/BACK/LEFT/RIGHT/STOP") # Guidance to the student
btn_fwd, btn_back, btn_left, btn_right, btn_stop = "FWD", "BACK", "LEFT", "RIGHT", "STOP" # Define command words
print("Accepted commands:", btn_fwd, btn_back, btn_left, btn_right, btn_stop) # Display allowed commands
while True: # Begin control loop
if last_command == btn_fwd: # Check forward command
print("Action: Move forward (simulated)") # Simulate forward movement
elif last_command == btn_back: # Check backward command
print("Action: Move backward (simulated)") # Simulate backward movement
elif last_command == btn_left: # Check left command
print("Action: Turn left (simulated)") # Simulate left turn
elif last_command == btn_right: # Check right command
print("Action: Turn right (simulated)") # Simulate right turn
elif last_command == btn_stop: # Check stop command
print("Action: Stop (simulated)") # Simulate stop
else: # Command not recognized
print("Action: Waiting for app command...") # Ask the student to press a button
time.sleep(0.5) # Slow down prints for readability
External explanation
- What it teaches: You connected your app to the robot and made it respond to your words.
- Why it works: The phone sends short messages; the robot runs a callback that reads them and sets last_command; the loop checks last_command and prints the matching action.
- Key concept: âCallbacks react; loops act.â
Story time
Your robot is your personal rover. You tap âFWDâ on your appâyour rover obeys. Soon, those words will drive real motors. Youâre piloting like a spacecraft captain.
Debugging (2)
Debugging 5.1.A â App connection failed
Problem: The app canât connect to âClu-Bots.â
Clues: The app shows âNot connected,â serial only prints âScanningâŠâ.
Broken code:
ble_p = ble_peripheral.BLESimplePeripheral('') # Empty name breaks discovery
print("Starting peripheral") # Missing useful status
Fixed code:
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Use a real name
print("Bluetooth: Peripheral 'Clu-Bots' ready") # Confirm advertising
Why it works: A valid advertised name lets your app find the device and connect.
Avoid next time: Never leave the name empty; print status so you know whatâs happening.
Debugging 5.1.B â Commands donât arrive
Problem: You press buttons but last_command never changes.
Clues: Serial shows no âReceived from app:â lines.
Broken code:
# Forgot to attach the callback
# handle.recv(handle_method) # This line is missing
Fixed code:
handle = ble_handle.Handle() # Create the handler
handle.recv(handle_method) # Attach callback so messages trigger
print("Callback attached: ready to receive commands") # Confirm setup
Why it works: Without the callback, incoming messages are ignored.
Avoid next time: Always attach the callback and add a serial print that confirms it.
Final checklist
- The app connects to âClu-Botsâ
- Serial shows received commands
- Changing the button label changes the printed action
Extras
- đ§ Student tip: Add a âMODEâ button that switches between âMANUALâ and âAUTO.â Print the current mode.
- đ§âđ« Instructor tip: Have students read serial prints out loudâverbalizing helps cement cause and effect.
- đ Glossary:
- Peripheral: The device that advertises a name and accepts connections.
- Central: The device that scans and initiates connections.
- Callback: A function that runs when a message arrives.
- đĄ Mini tips:
- Keep command words short (FWD, BACK).
- If prints go too fast, increase time.sleep to 1000 ms.
- Use serial messages to confirm every state change.