main.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # Rui Santos & Sara Santos - Random Nerd Tutorials
  2. # Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-w-bluetooth-low-energy-micropython/
  3. from micropython import const
  4. import asyncio
  5. import aioble
  6. import bluetooth
  7. import struct
  8. import machine
  9. import bme280_float as bme280
  10. import ssd1306
  11. import config
  12. i2c = machine.I2C(0, sda=machine.Pin(0), scl=machine.Pin(1))
  13. bme = bme280.BME280(i2c=i2c)
  14. oled = ssd1306.SSD1306_I2C(128, 64, i2c)
  15. temperature = 0
  16. pressure = 0
  17. humidity = 0
  18. #org.bluetooth.service.environmental_sensing
  19. _ENV_SENSE_UUID = bluetooth.UUID(0x181A)
  20. # org.bluetooth.characteristic.temperature
  21. _ENV_SENSE_TEMP_UUID = bluetooth.UUID(0x2A6E)
  22. # org.bluetooth.characteristic.pressure
  23. _ENV_SENSE_PRESSURE_UUID = bluetooth.UUID(0x2A6D)
  24. # org.bluetooth.characteristic.humidity
  25. _ENV_SENSE_HUMIDITY_UUID = bluetooth.UUID(0x2A6F)
  26. # org.bluetooth.characteristic.gap.appearance.xml
  27. _ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
  28. # How frequently to send advertising beacons.
  29. _ADV_INTERVAL_MS = 250_000
  30. # Register GATT server.
  31. envsense_service = aioble.Service(_ENV_SENSE_UUID)
  32. temp_characteristic = aioble.Characteristic(
  33. envsense_service, _ENV_SENSE_TEMP_UUID, read=True, notify=True)
  34. pressure_characteristic = aioble.Characteristic(
  35. envsense_service, _ENV_SENSE_PRESSURE_UUID, read=True, notify=True)
  36. humidity_characteristic = aioble.Characteristic(
  37. envsense_service, _ENV_SENSE_HUMIDITY_UUID, read=True, notify=True)
  38. aioble.register_services(envsense_service)
  39. # Helper to encode the characteristic encoding
  40. # (sint16, hundredths).
  41. def _encode_value(value):
  42. #print(int(value * 100))
  43. return struct.pack(f"<i", int(value * 100))
  44. # Get temperature and update characteristic
  45. async def sensor_task():
  46. global temperature, pressure, humidity
  47. while True:
  48. temperature, pressure, humidity = bme.read_compensated_data()
  49. #print(_encode_value(pressure/100))
  50. temp_characteristic.write(_encode_value(temperature), send_update=True)
  51. pressure_characteristic.write(_encode_value(pressure/100), send_update=True)
  52. humidity_characteristic.write(_encode_value(humidity), send_update=True)
  53. await asyncio.sleep_ms(1000)
  54. async def display_task():
  55. global temperature, pressure, humidity
  56. while True:
  57. oled.fill(0)
  58. oled.text("{:.2f} C".format(temperature), 0, 0)
  59. oled.text("{:.2f} hPa".format(pressure/100), 0, 10)
  60. oled.text("{:.2f}%".format(humidity), 0, 20)
  61. oled.show()
  62. await asyncio.sleep_ms(1000)
  63. # Serially wait for connections. Don't advertise while a central is connected.
  64. async def peripheral_task():
  65. while True:
  66. try:
  67. async with await aioble.advertise(
  68. _ADV_INTERVAL_MS,
  69. name=config.ble_peripheral_name,
  70. services=[_ENV_SENSE_UUID],
  71. appearance=_ADV_APPEARANCE_GENERIC_THERMOMETER,
  72. ) as connection:
  73. print("Connection from", connection.device)
  74. await connection.disconnected()
  75. except asyncio.CancelledError:
  76. # Catch the CancelledError
  77. print("Peripheral task cancelled")
  78. except Exception as e:
  79. print("Error in peripheral_task:", e)
  80. finally:
  81. # Ensure the loop continues to the next iteration
  82. await asyncio.sleep_ms(100)
  83. # Run both tasks
  84. async def main():
  85. t1 = asyncio.create_task(sensor_task())
  86. t2 = asyncio.create_task(display_task())
  87. t3 = asyncio.create_task(peripheral_task())
  88. await asyncio.gather(t1, t2, t3)
  89. asyncio.run(main())