📡 Level 3 – Advanced Communication

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

PartHow many?Pin connection
D1 R321USB cable
Built‑in Bluetooth1Internal (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:

  1. Create central and peripheral objects
  2. Create a handle object for callbacks
  3. Define a receive function (def)
  4. 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:

  1. Define send_text(msg)
  2. Call send_text with “Hello PC!”
  3. 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:

  1. Define reply_ack(text)
  2. In handle_method, call reply_ack with the incoming text
  3. 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:

  1. Setup Pin 13 as output
  2. Define do_cmd(text) to parse and act
  3. In handle_method, call do_cmd on each message
  4. 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:

  1. Setup LED (Pin 13)
  2. Define send_ping()
  3. Loop: blink LED and send ping
  4. 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:

  1. Create peripheral “Clu‑Bots” and callback handle.
  2. Define send_text(msg), reply_ack(text), and do_cmd(text).
  3. Register handle_method to print and process messages.
  4. Blink LED on activity; support “CMD:LED=ON/OFF”.
  5. 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.
On this page