Bluetooth#

The ESP32 has a built-in Bluetooth LE radio. LE stands for Low Energy. Unlike standard Bluetooth which is great for streaming audio, BLE sends only short strings but uses much less energy. It’s used e.g. in wireless mice and keyboards. And in our scale!

You can get the details on using the MicroPython Bluetooth Library online. Alternatively, just copy and adapt one of the examples in the MicroPython github repository.

We choose the second, easier option. ble_uart_peripheral.py sends arbitrary (short) strings to a connected device. Let’s download it and ble_advertising.py which it imports from the examples folder.

%cd $IOT_PROJECTS/balance/code
%%bash

wget -nc -P lib https://raw.githubusercontent.com/micropython/micropython/master/examples/bluetooth/ble_uart_peripheral.py
wget -nc -P lib https://raw.githubusercontent.com/micropython/micropython/master/examples/bluetooth/ble_advertising.py
Hide code cell output
cwd = /home/iot/iot49.org/docs/projects/balance/code
File ‘lib/ble_uart_peripheral.py’ already there; not retrieving.

File ‘lib/ble_advertising.py’ already there; not retrieving.

%connect balance
%rsync
Directories match

Download & start the Bluefruit LE Connect app to your smartphone. Then run the code in the next cell.

%softreset

import ble_uart_peripheral
ble_uart_peripheral.demo()

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!   softreset ...     !!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

rx:  hello
rx:  abc

Interrupted

The Bluefruit app will show your device as ESP32. Click connect, and then UART on the next screen to get a stream of numbers. Type some text into the box at the bottom of the screen and hit Send. The ESP32 prints the text you sent.

../../_images/bluefruit3.jpeg ../../_images/bluefruit2.jpeg ../../_images/bluefruit1.jpeg

Stop the running program.

We will now modify the demo function (reproduced below) to transmit the weights from the scale.

!tail -26 lib/ble_uart_peripheral.py
def demo():
    import time

    ble = bluetooth.BLE()
    uart = BLEUART(ble)

    def on_rx():
        print("rx: ", uart.read().decode().strip())

    uart.irq(handler=on_rx)
    nums = [4, 8, 15, 16, 23, 42]
    i = 0

    try:
        while True:
            uart.write(str(nums[i]) + "\n")
            i = (i + 1) % len(nums)
            time.sleep_ms(1000)
    except KeyboardInterrupt:
        pass

    uart.close()


if __name__ == "__main__":
    demo()

Here is the modified code.

%softreset

import ble_uart_peripheral
import bluetooth

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
from scale import Scale
from button import Button

# configure the Bluetooth UART
ble = bluetooth.BLE()
uart = ble_uart_peripheral.BLEUART(ble)

# Scale & Display
i2c = I2C(0, scl=Pin(22), sda=Pin(23))

oled_width = 128
oled_height = 32
oled = SSD1306_I2C(oled_width, oled_height, i2c)

scale = Scale()
tare_button = Button(15, scale.tare)

last_weight = 500
while True:
    weight = scale.measure()
    if abs(weight-last_weight) > 3:
        # send via Bluetooth
        uart.write("{:8.0f} gram\n".format(weight))
        # show on display
        oled.fill(0)
        oled.text("{:8.0f} gram".format(weight), 0, 12)
        oled.show()
        last_weight = weight

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!   softreset ...     !!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

tare

Interrupted

Congratulations! You have build a Bluetooth enabled scale.

If you feel adventurous, implement the “tare” function via Bluetooth. Or, if you are familiar with developing apps, write a custom one for the scale.