main.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. altitude = 0
  19. #org.bluetooth.service.environmental_sensing
  20. _ENV_SENSE_UUID = bluetooth.UUID(0x181A)
  21. # org.bluetooth.characteristic.temperature
  22. _ENV_SENSE_TEMP_UUID = bluetooth.UUID(0x2A6E)
  23. # org.bluetooth.characteristic.pressure
  24. _ENV_SENSE_PRESSURE_UUID = bluetooth.UUID(0x2A6D)
  25. # org.bluetooth.characteristic.humidity
  26. _ENV_SENSE_HUMIDITY_UUID = bluetooth.UUID(0x2A6F)
  27. # org.bluetooth.characteristic.altitude
  28. _ENV_SENSE_ALTITUDE_UUID = bluetooth.UUID(0x2AB3)
  29. # org.bluetooth.characteristic.gap.appearance.xml
  30. _ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
  31. # How frequently to send advertising beacons.
  32. _ADV_INTERVAL_MS = 250_000
  33. # Register GATT server.
  34. envsense_service = aioble.Service(_ENV_SENSE_UUID)
  35. temp_characteristic = aioble.Characteristic(
  36. envsense_service, _ENV_SENSE_TEMP_UUID, read=True, notify=True)
  37. pressure_characteristic = aioble.Characteristic(
  38. envsense_service, _ENV_SENSE_PRESSURE_UUID, read=True, notify=True)
  39. humidity_characteristic = aioble.Characteristic(
  40. envsense_service, _ENV_SENSE_HUMIDITY_UUID, read=True, notify=True)
  41. altitude_characteristic = aioble.Characteristic(
  42. envsense_service, _ENV_SENSE_ALTITUDE_UUID, read=True, notify=True)
  43. aioble.register_services(envsense_service)
  44. # Helper to encode the characteristic encoding
  45. # (sint16, hundredths).
  46. def _encode_value(value):
  47. #print(int(value * 100))
  48. return struct.pack(f"<i", int(value * 100))
  49. # Get temperature and update characteristic
  50. async def sensor_task():
  51. global temperature, pressure, humidity, altitude
  52. while True:
  53. temperature, pressure, humidity = bme.read_compensated_data()
  54. altitude = bme.altitude
  55. #print(_encode_value(pressure/100))
  56. temp_characteristic.write(_encode_value(temperature), send_update=True)
  57. pressure_characteristic.write(_encode_value(pressure/100), send_update=True)
  58. humidity_characteristic.write(_encode_value(humidity), send_update=True)
  59. altitude_characteristic.write(_encode_value(altitude), send_update=True)
  60. await asyncio.sleep_ms(1000)
  61. async def display_task():
  62. global temperature, pressure, humidity, altitude
  63. while True:
  64. oled.fill(0)
  65. oled.text("{:.2f} C".format(temperature), 0, 0)
  66. oled.text("{:.2f} hPa".format(pressure/100), 0, 10)
  67. oled.text("{:.2f}%".format(humidity), 0, 20)
  68. oled.text("{:.2f} m".format(altitude), 0, 30)
  69. oled.show()
  70. await asyncio.sleep_ms(1000)
  71. # Serially wait for connections. Don't advertise while a central is connected.
  72. async def peripheral_task():
  73. while True:
  74. try:
  75. async with await aioble.advertise(
  76. _ADV_INTERVAL_MS,
  77. name=config.ble_peripheral_name,
  78. services=[_ENV_SENSE_UUID],
  79. appearance=_ADV_APPEARANCE_GENERIC_THERMOMETER,
  80. ) as connection:
  81. print("Connection from", connection.device)
  82. await connection.disconnected()
  83. except asyncio.CancelledError:
  84. # Catch the CancelledError
  85. print("Peripheral task cancelled")
  86. except Exception as e:
  87. print("Error in peripheral_task:", e)
  88. finally:
  89. # Ensure the loop continues to the next iteration
  90. await asyncio.sleep_ms(100)
  91. # Run both tasks
  92. async def main():
  93. t1 = asyncio.create_task(sensor_task())
  94. t2 = asyncio.create_task(display_task())
  95. t3 = asyncio.create_task(peripheral_task())
  96. await asyncio.gather(t1, t2, t3)
  97. asyncio.run(main())