main.py 4.0 KB

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