超簡單做出低功耗藍牙温度計-Part 2(nRF52840 Dongle + TMP102 + CircuitPython)

同樣都使用nRF52840 Dongle, 上一次是用MicroPython, 這一次來用用CircuitPython。不管怎麼說, CircuitPython有Adafruit在支持, 文件和資源是更多的。而且, 目前CircuitPython支持的MCU就是以SAMD21/51和nRF系列為主。但要讓nRF52840 Dongle可以跑CircuitPython, 我們要先做些工作, 網路上有2個地方可以參考, 第1個是這篇文章, Eric Pietrowicz使用PCA10056開發板上的JLink除錯器來燒錄具UF2功能的Bootloader。

Bluetooth Low Energy with CircuitPython on a nRF52840 USB Dongle

第2個是這個影片, rdagger使用的是OpenOCD除錯器配合Raspberry Pi 3B來燒錄具UF2功能的Bootloader到nRF52840 Dongle。


當然, 直接使用JLink來燒錄也是可以。

具UF2功能的Bootloader是CircuitPython開發板的標配, 這個Bootloader讓開發板一插到電腦USB, 就會出現一個小硬碟, 讓你感覺這個開發板就是一個小磁碟機, 接下來我們要燒錄firmware, 就只要直接拖拉firmware檔案進去就可以了。

nRF52840 Dongle的UF2 Bootloader, 以及其CircuitPython firmware可以在以下連結找到

https://circuitpython.org/board/pca10059/

依照前面提到的文章說明, 把nRF52840 Dongle的Bootloader燒成具UF2功能的, 之後插入這支Dongle到電腦的USB埠, 就會出現一個名為NRF52BOOT之類的小磁碟機, 然後將CircuitPython的.uf2 firmware拖拉進去, 就會打造出一個跑CircuitPython的開發板了。

這個過程需要一些工作, 如果覺得太累, 也可以買一個出廠就已經幫你燒好UF2 Bootloader的開發板, Adafruit Feather nRF52840 Express就是一個, SEEED STUDIO XIAO NRF52840也是。

燒好CircuitPython firmware後, 插入nRF52840 Dongle, 就會看到出現一個名為CIRCUITPY的小磁碟機:


其中有一個名為lib的目錄, 是用來放硬體驅動的, 而code.py是一開機就會執行的python程式。為了讀取TMP102温度的數值, 同樣我們需要一支驅動程式, 這可以使用我們先前那篇文章的那支驅動來修改。啊! 同樣都是Python, MicroPython和CircuitPython也會有不同哦! 


好在, 要改的也不多, 如上圖, 把_read_register()這個函數小改一下, 就可以了。這樣我們就有一個可以在CircuitPython使用的TMP102驅動。同樣把這個驅動命名為tmp102.py, 然後copy到CIRCUITPY這個磁碟的lib目錄去。不過, 因為空間和效率的考量, 通常會使用mpy-cross工具, 將.py轉成.mpy的格式。

接下來, 試試用用這支驅動來讀讀温度吧!


from tmp102 import Tmp102
import board
import busio
import time

i2c = busio.I2C(board.P0_29, board.P0_31)
sensor = Tmp102(i2c, 0x48)


# periodic read
i2c.try_lock() 
sensor.wakeup()
print(sensor.get_TempC(sensor.temperature()))
i2c.unlock()

# one-shot read
i2c.try_lock()
sensor.sleep()

run = True
while run:
    try:
        sensor.set_one_shot()
        print(sensor.get_TempC(sensor.get_one_shot()))
        time.sleep(1.0)
    except:
        run = False

i2c.unlock()
這裡可以看到CircuitPython的寫法還是和MicroPython有一些小差異的! 我們在此使用busio來將I2C設置起來也是nRF52840這顆MCU特定的。在此, 我將pin 0.29指定為SCL, pin 0.31指定為SDA, 所以在硬體接線時, 也要如此接。把上面這個程式存到CIRCUITPY這個磁碟的code.py檔案, 打開終端機, 觀察:
如上圖, 出現温度值, 那就是TMP102感測器已經可以正常運作了。


下一步, 把藍牙功能跑起來, 可以先參考:

基本上, Adafruit已經把許多工作做完, 包括MCU的驅動程式, 和手機上的App。nRF52840 MCU BLE驅動, 目前我們只要先搬2個目錄就好:

這2個目錄來自CircuitPython Librarys (adafruit cricuitpython bundle) https://circuitpython.org/libraries, 請依自己開發板上CircuitPython firmware版本來選擇相對應的下載版本。
手機上的App, 則到App Store, 找Bluefruit Connect。

並將下面程式, 放到開發板上的code.py

# CircuitPython Bluefruit LE Connect Plotter Example

import time
import board
import busio
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

from tmp102 import Tmp102
i2c = busio.I2C(board.P0_29, board.P0_31)
sensor = Tmp102(i2c, 0x48)
i2c.try_lock()
sensor.sleep()

ble = BLERadio()
uart_server = UARTService()
advertisement = ProvideServicesAdvertisement(uart_server)


while True:
    # Advertise when not connected.
    ble.start_advertising(advertisement)
    while not ble.connected:
        pass
    ble.stop_advertising()

    while ble.connected:
        sensor.set_one_shot()
        tempc = sensor.get_TempC(sensor.get_one_shot()) 
        print(tempc)
        uart_server.write("{}\n".format(tempc))
        time.sleep(1.0)
打開手機的Bluefruit Connect App, 連入後, 會看到如下圖:


此時, 我們可以有2個地方查看温度值, 一個是UART的輸出, 一個是Plotter:
點UART:
可以看到每秒都會收到一個温度值, 就和我們在終端機上看到的輸出是一樣的! 這當然是因為我們程式是這樣寫的。到這裡, 我們已經完成由BLE來收取nRF52840 Dongle取得的TMP102温度值。

點Plotter:
更好的是, Bluefruit Connect也提供畫圖的功能, 如上圖, 我們什麼都不用做, 只要選這個選項, 就可以看到温度的變化圖形。這樣是不是超簡單就做出BLE温度計來了呢? 

留言

這個網誌中的熱門文章

D-BUS學習筆記

關於藍牙裝置找尋(inquiry, scan)兩三事

Cisco Switch學習筆記: EtherChannel