Project 3.6: "Bluetooth R32-PC"
🚀 Project 3.6 – Bluetooth R32 ↔ PC
🎯 What you’ll learn
- ✅ Goal 1: Initialize built‑in Bluetooth and advertise as “Clu‑Bots”
- ✅ Goal 2: Send and receive simple text messages over Bluetooth
- ✅ Goal 3: Use small helper functions (def) for clean, reusable actions
Key ideas
- Short definition: Bluetooth lets your board talk wirelessly to nearby devices.
- Real‑world link: Keyboards, mice, gamepads, and sensors use Bluetooth to send data to computers and phones.
🧱 Blocks glossary (used in this project)
- Bluetooth peripheral: The device that advertises a name (e.g., “Clu‑Bots”) and sends data.
- Bluetooth central: The device that scans and connects to a peripheral to receive data.
- Callback (receive): A function that runs automatically when a message arrives.
- Serial print: Shows Bluetooth events and messages on your computer.
- Variable: Stores text and status like “connected” or “message”.
- def function: Defines a reusable action (e.g., send_text(msg)).
- Loop: Keeps advertising, checking, and interacting.
🧰 What you need
| Part | How many? | Pin connection |
|---|---|---|
| D1 R32 | 1 | USB cable |
| Built‑in Bluetooth | 1 | Internal (no pins) |
- No external Bluetooth module needed — D1 R32 includes it.
- Optional: Joystick Shield (buttons A–F) if you want hotkeys later (not required here).
🔌 Wiring tip: Keep the board powered over USB and within 1–3 meters of the PC for pairing tests.
📍 Pin map snapshot: Bluetooth uses internal radio — no physical pins.
✅ Before you start
- Plug in USB and open the serial monitor.
- Test print shows:
print("Ready!") # Confirm serial is working
🎮 Microprojects (5 mini missions)
🎮 Microproject 3.6.1 – Initialize Bluetooth and advertise
Goal: Start Bluetooth, choose a device name, and set a receive callback.
Blocks used:
- Bluetooth peripheral: Create device “Clu‑Bots”
- Callback: Print received data
- Serial print: Log init steps
Block sequence:
- Create central and peripheral objects
- Create a handle object for callbacks
- Define a receive function (def)
- Register callback and advertise
MicroPython code:
# Microproject 3.6.1 – Initialize Bluetooth and advertise
import ble_central # Load Bluetooth central helper
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback handle
print("[Init] Bluetooth starting") # Serial: announce Bluetooth init
ble_c = ble_central.BLESimpleCentral() # Create central role object (host)
print("[Init] Central ready") # Serial: central created
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral with name 'Clu-Bots'
print("[Init] Peripheral named 'Clu-Bots'") # Serial: peripheral created
handle = ble_handle.Handle() # Create handle to manage callbacks
print("[Init] Handle ready") # Serial: handle created
def handle_method(msg): # Define a receive callback function
# msg: incoming text/message from the Bluetooth link
print("[Recv] Message:", msg) # Serial: show received message
handle.recv(handle_method) # Register our receive function with the handle
print("[BT] Advertising as 'Clu-Bots'") # Serial: advertising status
Reflection: You gave your robot a wireless name and ears to hear messages.
Challenge:
- Easy: Change the device name to “Clu‑Bots R32”.
- Harder: Add a second callback that prints message length too.
🎮 Microproject 3.6.2 – Send a text message from the board
Goal: Create a helper function and send a short message (“Hello PC!”).
Blocks used:
- def function: send_text(msg)
- Bluetooth peripheral: Send data
- Serial print: Confirm send
Block sequence:
- Define send_text(msg)
- Call send_text with “Hello PC!”
- Print confirmation
MicroPython code:
# Microproject 3.6.2 – Send a text message
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback handle
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral again (named)
print("[Init] Peripheral 'Clu-Bots' ready") # Serial: confirm peripheral
handle = ble_handle.Handle() # Create handle for callbacks
print("[Init] Handle ready") # Serial: confirm handle
def send_text(msg): # Define a helper to send text
# msg: string to transmit over Bluetooth
ble_p.send(msg) # Send the message via Bluetooth peripheral
print("[Send] TX:", msg) # Serial: confirm the send
def handle_method(msg): # Define receive callback
# msg: incoming text over Bluetooth
print("[Recv] RX:", msg) # Serial: show the message
handle.recv(handle_method) # Register callback
send_text("Hello PC!") # Send demo text to the connected device
Reflection: A tiny helper function makes sending text clean and reusable.
Challenge:
- Easy: Change the message to include your name.
- Harder: Add a timestamp in the message like “Hello 10:32”.
🎮 Microproject 3.6.3 – Echo: receive and reply
Goal: When a message arrives, reply with “ACK: ”.
Blocks used:
- Callback: Receive message
- def function: reply with ACK
- Serial print: Show both RX and TX
Block sequence:
- Define reply_ack(text)
- In handle_method, call reply_ack with the incoming text
- Print logs
MicroPython code:
# Microproject 3.6.3 – Echo back ACK when a message arrives
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback handle
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral instance
print("[Init] Peripheral 'Clu-Bots'") # Serial: confirm
handle = ble_handle.Handle() # Create callback handler
print("[Init] Handle ready") # Serial: confirm
def reply_ack(text): # Define ACK reply helper
# text: the received message to acknowledge
ack = "ACK: " + str(text) # Build acknowledgment string
ble_p.send(ack) # Send ACK back over Bluetooth
print("[Send] TX:", ack) # Serial: show sent ACK
def handle_method(msg): # Define receive callback
# msg: incoming text from Bluetooth
print("[Recv] RX:", msg) # Serial: show received text
reply_ack(msg) # Call our ACK helper to respond
handle.recv(handle_method) # Register receive callback
print("[BT] Echo mode ready") # Serial: status info
Reflection: Your robot listens and answers — an echo is the first step in a protocol.
Challenge:
- Easy: Change ACK to “OK: ”.
- Harder: Reply only if the message starts with “CMD:”.
🎮 Microproject 3.6.4 – Status messages and simple commands
Goal: Respond to “CMD:LED=ON” or “CMD:LED=OFF” with a status.
Blocks used:
- Callback: Parse command text
- Digital output: Control a status LED (Pin 13)
- def function: do_cmd(text)
Block sequence:
- Setup Pin 13 as output
- Define do_cmd(text) to parse and act
- In handle_method, call do_cmd on each message
- Send status back
MicroPython code:
# Microproject 3.6.4 – Parse simple commands over Bluetooth
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback handle
import machine # Load hardware pin library
pin13 = machine.Pin(13, machine.Pin.OUT) # Prepare LED output on Pin 13
print("[Init] LED on Pin 13") # Serial: confirm LED setup
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral
print("[Init] Peripheral 'Clu-Bots'") # Serial: confirm
handle = ble_handle.Handle() # Create handle
print("[Init] Handle ready") # Serial: confirm
def do_cmd(text): # Define a command parser helper
# text: full message received over Bluetooth
s = str(text) # Ensure it's a string
if s == "CMD:LED=ON": # If command to turn LED ON
pin13.value(1) # Set LED HIGH (ON)
ble_p.send("STATUS:LED=ON") # Send status confirmation
print("[Action] LED ON") # Serial: log action
elif s == "CMD:LED=OFF": # If command to turn LED OFF
pin13.value(0) # Set LED LOW (OFF)
ble_p.send("STATUS:LED=OFF") # Send status confirmation
print("[Action] LED OFF") # Serial: log action
else: # If unknown command
ble_p.send("ERROR:UNKNOWN_CMD") # Send error message
print("[Warn] Unknown command:", s) # Serial: warn
def handle_method(msg): # Define receive callback
# msg: incoming Bluetooth text
print("[Recv] RX:", msg) # Serial: show incoming text
do_cmd(msg) # Parse and perform command
handle.recv(handle_method) # Register callback
print("[BT] Command mode ready") # Serial: status info
Reflection: Commands that change hardware make Bluetooth feel powerful.
Challenge:
- Easy: Add “CMD:LED=TOGGLE”.
- Harder: Use “CMD:NAME=YourName” to change the device greeting message.
🎮 Microproject 3.6.5 – Keep‑alive and “connected” indicator
Goal: Send a ping every 2 seconds and toggle LED to show link activity.
Blocks used:
- def function: send_ping()
- Delay/loop: Timing for keep‑alive
- Digital output: Blink LED on activity
Block sequence:
- Setup LED (Pin 13)
- Define send_ping()
- Loop: blink LED and send ping
- Print logs
MicroPython code:
# Microproject 3.6.5 – Keep-alive pings and activity LED
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback handle
import machine # Load hardware pin library
import time # Load time library
pin13 = machine.Pin(13, machine.Pin.OUT) # Prepare LED output
print("[Init] LED activity on 13") # Serial: confirm LED
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral
print("[Init] Peripheral 'Clu-Bots'") # Serial: confirm
handle = ble_handle.Handle() # Create handle
print("[Init] Handle ready") # Serial: confirm
def send_ping(): # Define keep-alive helper
# Send a short heartbeat over Bluetooth
ble_p.send("PING") # Transmit PING message
print("[Send] PING") # Serial: log ping
def handle_method(msg): # Define receive callback
# msg: incoming Bluetooth text
print("[Recv] RX:", msg) # Serial: log receive
pin13.value(1) # LED ON to indicate activity
time.sleep_ms(100) # Short blink ON
pin13.value(0) # LED OFF after blink
handle.recv(handle_method) # Register callback
while True: # Main keep-alive loop
send_ping() # Send heartbeat
pin13.value(1) # LED ON before wait
time.sleep_ms(80) # Short blink
pin13.value(0) # LED OFF
time.sleep_ms(2000) # Wait 2 seconds between pings
Reflection: A heartbeat makes your link feel alive — great for testing connectivity.
Challenge:
- Easy: Change ping period to 1 second.
- Harder: Count missed replies and print “Link weak” after 3 misses.
✨ Main project – Bluetooth messaging and simple commands
🔧 Blocks steps (with glossary)
- Bluetooth peripheral: Advertise as “Clu‑Bots” and send/receive text
- Callback: Run a function automatically on new messages
- def function: Helpers for send, ACK, and command parsing
- Digital output: Control LED as feedback
- Serial print: Clear logs for events and actions
Block sequence:
- Create peripheral “Clu‑Bots” and callback handle.
- Define send_text(msg), reply_ack(text), and do_cmd(text).
- Register handle_method to print and process messages.
- Blink LED on activity; support “CMD:LED=ON/OFF”.
- Send PING every 2 seconds as keep‑alive.
🐍 MicroPython code (mirroring blocks)
# Project 3.6 – Bluetooth R32 ↔ PC: Messaging + Commands
import ble_peripheral # Load Bluetooth peripheral helper
import ble_handle # Load Bluetooth callback handle
import machine # Load hardware pin library
import time # Load time library
pin13 = machine.Pin(13, machine.Pin.OUT) # Prepare LED output on Pin 13
print("[Init] LED ready on 13") # Serial: LED init
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Create peripheral named 'Clu-Bots'
print("[Init] Peripheral 'Clu-Bots' active") # Serial: peripheral active
handle = ble_handle.Handle() # Create handle for callbacks
print("[Init] Handle attached") # Serial: handle ready
def send_text(msg): # Helper: send a text message
ble_p.send(msg) # Send Bluetooth text
print("[Send] TX:", msg) # Serial: confirm send
def reply_ack(text): # Helper: send ACK reply
ack = "ACK: " + str(text) # Build ack string
ble_p.send(ack) # Send ACK over Bluetooth
print("[Send] TX:", ack) # Serial: confirm ack send
def do_cmd(text): # Helper: parse and run commands
s = str(text) # Ensure string
if s == "CMD:LED=ON": # If command to turn LED ON
pin13.value(1) # LED ON
ble_p.send("STATUS:LED=ON") # Status back to PC
print("[Action] LED ON") # Serial: action log
elif s == "CMD:LED=OFF": # If command to turn LED OFF
pin13.value(0) # LED OFF
ble_p.send("STATUS:LED=OFF") # Status back to PC
print("[Action] LED OFF") # Serial: action log
else: # Unknown command
ble_p.send("ERROR:UNKNOWN_CMD") # Send error status
print("[Warn] Unknown:", s) # Serial: warn
def handle_method(msg): # Callback: when a message arrives
print("[Recv] RX:", msg) # Serial: show received text
reply_ack(msg) # Send ACK reply
do_cmd(msg) # Try to execute command
pin13.value(1) # Blink LED for activity
time.sleep_ms(80) # Short blink ON
pin13.value(0) # LED OFF
handle.recv(handle_method) # Register our callback
print("[BT] Messaging and command mode ready") # Serial: ready status
while True: # Main loop: keep-alive pings
send_text("PING") # Send heartbeat ping
time.sleep_ms(2000) # Wait 2 seconds, repeat
📖 External explanation
- What it teaches: How to advertise a Bluetooth device, send/receive text, and react to simple commands.
- Why it works: The peripheral names itself, a callback handles data, and helper functions keep code clear and reusable.
- Key concept: “Define, then use” (def) makes complex behaviors easy to understand and maintain.
✨ Story time
Your robot just learned to chat. It says “PING,” hears “CMD:LED=ON,” and replies “ACK: …” like a polite, wireless teammate.
🕵️ Debugging (2)
🐞 Debugging 3.6.A – No messages arriving
Problem: You see init logs, but nothing prints under “[Recv]”.
Clues: PC isn’t paired/connected; handle not registered.
Broken code:
# Forgot to register the receive callback
# handle.recv(handle_method) # Missing line
Fixed code:
handle.recv(handle_method) # Register callback before interacting
print("[BT] Callback registered") # Confirm registration
Why it works: Without the callback, messages are ignored. Register it early.
🐞 Debugging 3.6.B – Messages sent but not seen on PC
Problem: “[Send] TX: …” appears, but PC shows nothing.
Clues: Device not connected; name mismatch; app not listening.
Broken code:
ble_p = ble_peripheral.BLESimplePeripheral('Wrong-Name') # Advertising unexpected name
Fixed code:
ble_p = ble_peripheral.BLESimplePeripheral('Clu-Bots') # Use expected name
# Then pair/connect from the PC Bluetooth settings or app that reads text
Why it works: The PC needs to connect to the correct device name and listen to the right characteristic.
✅ Final checklist
- I saw “[BT] Advertising as ‘Clu‑Bots’” and init logs
- I sent “Hello PC!” and saw “[Send] TX: …”
- I saw “[Recv] RX: …” when data arrived
- “CMD:LED=ON/OFF” changed the LED and sent status back
- PING messages appeared every 2 seconds
📚 Extras
- 🧠 Student tip: Keep messages short and clear — commands should look like “CMD:LED=ON”.
- 🧑🏫 Instructor tip: Demonstrate pairing in the OS and use a simple BLE terminal app to view messages.
- 📖 Glossary:
- Peripheral: The device that advertises and sends data.
- Central: The device that scans and connects to peripherals.
- Callback: A function that runs automatically on events like “message arrived”.
- 💡 Mini tips:
- Define helper functions first; use them in the loop.
- Log succinctly — one line per event/action.
- Keep pings spaced (1000–2000 ms) to avoid spam.