đŸ“± Level 5 – App Communication

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

PartHow many?Pin connection
D1 R321USB cable (30 cm)
Smartphone (Android/iOS)1Bluetooth 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:

  1. Initialize a variable last_command = “NONE”.
  2. Print “Open the app and press a button”.
  3. 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:

  1. Init central (host) and peripheral (name “Clu-Bots”).
  2. Scan for devices.
  3. Connect to name “Clu-Bots”.
  4. 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:

  1. Define handle_method(key1, key2, key3, keyx).
  2. In the function, print the message.
  3. Save message to last_command.
  4. 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:

  1. Create a status string like “STATUS:OK”.
  2. Print it to serial (students will read this and send back via app UI).
  3. 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:

  1. Set variables for custom names.
  2. Print them so students see the current mapping.
  3. 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:

  1. Init BLE peripheral named “Clu-Bots” → app can connect.
  2. Init BLE central → scan → connect by name “Clu-Bots” → verify.
  3. Register receive-message callback → handle_method prints and stores commands.
  4. 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.
On this page