Raspberry Pi Pico W jetzt mit Bluetooth - Teil 1 - AZ-Delivery

In the Blog post from January 3rd, 2023 We had introduced how the Raspberry Pi Pi Pi Pi W with the temperature sensors BME280 and DHT20 locally shows the temperature and humidity on a 0.96 ”or 1.3“ OLED display and at the same time provides the data in the home WLAN. This ability of the Pico W is realized with the Infineon Chip Cyw43439 for WLAN 2.4 GHz and has been available since the performance on June 30, 2022.

In principle, this chip can also enable Bluetooth 5.2; So far, this has not been supported by the firmware. It took almost a year and obviously required considerable manpower to adapt micropython and the firmware. More on that in the Press release from Eben Upton of June 14, 2023.

The fastest way to install the latest firmware is to download the *.uf2 file for Raspberry Pi Pico W With Wi-Fi and Bluetooth Le Support. When writing the blog post it was this file: Micropython firmware pico-w-130623.uf2. Then hold the boat button pressed and connect the Pico W via USB with the PC. In Explorer, the Pico appears like a USB stick, so that the file *.uf2 can be moved to the pico with "drag and drop". The USB drive disappears a few seconds later and the Pico W can be operated with Thonny (see also previous blog posts on the subject of Pico, First partSecond part, third part,  Weather station with the Sensor BME280 and the 0.96 inch OLED SSD1306 display). I had previously secured my other PICO W programs on the PC. That would not have been necessary, because the micropython programs were not deleted when the firmware updates.

The revision of the documentation and the creation of program examples had a large part in adapting the firmware. Even if you already know the following websites - it is worth downloading the new versions of the brochure "Connecting to the Internet with Raspberry Pi Pico W" and the Micropython Examples (Examples)

https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html

https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf

https://github.com/micropython/micropython/tree/master/examples/bluetooth

https://docs.micropython.org/en/latest/library/bluetooth.html

It is idle to understand the complexity of Bluetooth and to read several thousand pages documentation or specification. As so often, the pragmatic approach is: study examples and adapt them for their own purpose. Let's go.

In my opinion, it is difficult to understand and yet recommended chapters 4 "About Bluetooth" and Chapter 6 "Working with Bluetooth in Micropython" of the brochure "Connecting to the Internet with Raspberry Pi Pico W". Here I find an example on page 37ff how to measure the temperature with the Pico W and provide via Bluetooth. The use of the internal temperature sensor is certainly suitable for the overheating protection of the microcontroller, but definitely does not indicate the ambient temperature. Therefore, I “married” this program example with my program for the temperature sensor DHT20 and the 1.3 ”OLED from the January blog, but without the WiFi.

Here is the circuit as in the blog of January, the counting loop (counter) I left out, The LED flashes every second.

Hardware used:

1

Raspberry Pi Pico W With current firmware

1

Temperature/rel. Air humidity sensor DHT20

1

1.3 “OLED

1

Breadboard, jumper cable

PC with Thonny, Android smartphone/tablet


Program code (download):

 # Example Temperature Sensor and Bluetooth, Based ON
 # Connecting to the Internet with Raspberry Pi Pico W
 # Copyright © 2022-2023 Raspberry Pi Ltd
 # Licensed Under a Creative Commons Attribution Noderivative 4.0 International (CC BY-ND).
 # Example on page 37ff
 # Modified for Temperature Sensor DHT10 for AZ-Delivery
 import bluetooth
 import random
 import struct
 import time
 import machine
 import Ubinascii
 From ble_advertising import Advertising_payload
 From micropython import const
 from machine import Pin
 ## modified for AZ-Delivery
 import sh1106
 from dht20 import DHT20
 from machine import Pin, I2C
 sda=Pin(12)
 scl=Pin(13)
 i2c=I2C(0, sda=sda, scl=scl, freq=400000)
 WIDTH = 128
 HIGHT = 64
 oled = sh1106.SH1106_I2C(128, 64, i2c, None, 0x3c,rotate=180)
 dht20 = DHT20(0x38, i2c)           # 0x38 ist die i2c-Adresse
 ##
 
 
 _IRQ_CENTRAL_CONNECT = const(1)
 _IRQ_CENTRAL_DISCONNECT = const(2)
 _IRQ_GATTS_INDICATE_DONE = const(20)
 
 
 _FLAG_READ = const(0x0002)
 _FLAG_NOTIFY = const(0x0010)
 _FLAG_INDICATE = const(0x0020)
 
 
 # org.bluetooth.service.environmental_sensing
 _ENV_SENSE_UUID = bluetooth.UUID(0x181A)
 
 
 # org.bluetooth.characteristic.temperature
 _TEMP_CHAR = (
     bluetooth.UUID(0x2A6E),
     _FLAG_READ | _FLAG_NOTIFY | _FLAG_INDICATE,
 )
 _ENV_SENSE_SERVICE = (
     _ENV_SENSE_UUID,
    (_TEMP_CHAR,),
 )
 
 
 # org.bluetooth.characteristic.gap.appearance.xml
 _ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
 
 
 class BLETemperature:
     def __init__(self, ble, name=""):
         self._sensor_temp = machine.ADC(4)
         self._ble = ble
         self._ble.active(True)
         self._ble.irq(self._irq)
        ((self._handle,),) = self._ble.gatts_register_services((_ENV_SENSE_SERVICE,))
         self._connections = set()
         if len(name) == 0:
             name = 'Pico %s' % ubinascii.hexlify(self._ble.config('mac')[1],':').decode().upper()
         print('Sensor name %s' % name)
         self._payload = advertising_payload(
         name=name, services=[_ENV_SENSE_UUID]
        )
         self._advertise()
 
 
     def _irq(self, event, data):
         # Track connections so we can send notifications.
         if event == _IRQ_CENTRAL_CONNECT:
             conn_handle, _, _ = data
             self._connections.add(conn_handle)
         elif event == _IRQ_CENTRAL_DISCONNECT:
             conn_handle, _, _ = data
             self._connections.remove(conn_handle)
             # Start advertising again to allow a new connection.
             self._advertise()
         elif event == _IRQ_GATTS_INDICATE_DONE:
             conn_handle, value_handle, status = data
 
 
     def update_temperature(self, notify=False, indicate=False):
         # Write the local value, ready for a central to read.
         temp_deg_c = self._get_temp()
         print("write temp %.2f degc" % temp_deg_c);
         self._ble.gatts_write(self._handle, struct.pack("<h", int(temp_deg_c * 100)))
         if notify or indicate:
             for conn_handle in self._connections:
                 if notify:
                     # Notify connected centrals.
                     self._ble.gatts_notify(conn_handle, self._handle)
                 if indicate:
                     # Indicate connected centrals.
                     self._ble.gatts_indicate(conn_handle, self._handle)
 
 
     def _advertise(self, interval_us=500000):
         self._ble.gap_advertise(interval_us, adv_data=self._payload)
 
 
     def _get_temp(self):
 ## modified for AZ-Delivery
 ## replace internal temperature sensor with DHT20 and OLED
 #         conversion_factor = 3.3 / (65535)
 #         reading = self._sensor_temp.read_u16() * conversion_factor
 #
 #         return 27 - (reading - 0.706) / 0.001721
         measurements = dht20.measurements
         tempC = measurements['t']
         humRH = measurements['rh']
         print("Temperature: " + str(tempC))
         print("Humidty: " + str(humRH))
         print(">-----------<")
         #Write data to display
         oled.fill(0)
         oled.text("Pico W, DHT20 ",6,0)
         oled.text("Temp:" + str(tempC),6,14)
         oled.text("Humi:" + str(humRH),6,42)
         oled.show()
         return tempC
 ##
 
 
 def demo():
     ble = bluetooth.BLE()
     temp = BLETemperature(ble)
     counter = 0
     led = Pin('LED', Pin.OUT)
     while True:
         if counter % 10 == 0:
             temp.update_temperature(notify=True, indicate=False)
         led.toggle()
         time.sleep_ms(1000)
         counter += 1
 
 
 if __name__ == "__main__":
     demo()

Wichtig ist, dass das MicroPython-Beispielprogramm ble_advertising.py auf den Pico W kopiert wird. Ansonsten erhält man bei der Zeile „From ble_advertising import advertising_payload " an error message.

The changes made compared to the sample program are at the beginning when importing and instantiation of the DHT20 and the OLED, as well as in the function _get_temp Between two comment characters (## hash tag ##).

My modified program runs surprisingly quickly after banal error messages, temperature and humidity are displayed on the OLED and the internal LED of the PICO flashes every second. On the subsequent screen photo again the modified self -defined function _get_temp And the data edition in Thonny's shell.

But is the temperature also displayed on the smartphone via Bluetooth? To do this, I install the Lightblue app on my smartphone and later on my Android tablet via the Play Store. Of course, Bluetooth is activated.

Here is the logo of the Lightblue app.

The provider is the company Punchthrough Design.

The name explains the (for me) threatening logo.


After the start, the app scans the nearby area according to BT-capable devices. In addition to the previously known devices, or those with weak signals, the PICO is displayed immediately.

I tap Connect at the bottom right. A new screen appears, in which I have to scroll further down with my preselected font size.

At the bottom I find a small arrow for the temperature display under Environmental Sensing. My finger pressure on the arrow opens the next screen. And here, too, I have to scroll down.

The Subscribe/unsubscribe button is located under Read/Indicated Values. After I have subscribed to the Server PICO28: XX, the temperature and the date time group are output every 10 seconds. First a cryptic statement. NOh switching the data format to "Signed Little-Endian" the temperature appears in hundredths of degrees Celsius, i.e. 2391 means 23.91 ° ​​C.

Now my Android tablet is used. I also scan there for BT devices and don't find a Pico. That was the expected result for me. So I understood the text from the above brochure. The Pico W as a server initially offers its services. For that is the module ble_advertising.py responsible. It happens as long as no client (smartphone or tablet) subscribed to the service. I had done that with typing on Subscribe. So when the smartphone is connected to the PICO W, it stops its service offer.

Now I separate the smartphone with unsubscribes and (twice arrow back) disconnect. Now the server offers all clients again until I press Subscribe on the tablet and my smartphone no longer recognize the Pico W.

Up to this point I have invested many hours of research and reading on the subject of Bluetooth, and yet I feel at the beginning. I hope I could make it easier for you to get started. When it comes to robot car with Pico W and Bluetooth, I have Martin O’Hanlon from the Raspberry Pi Foundation (author of the Bluedot app for the Raspberry Pi Mikro Computer/Python, see Blog from June 6th, 2022) written on whether he adapts his app for Micropython. His answer is promising, but a timely solution is not to be expected.

Have fun with your first attempts with the Raspberry Pi Pico W and Bluetooth.

DisplaysProjekte für anfängerRaspberry piSensoren

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery