|
| 1 | +# Bluefruit Playground server program, to run on CLUE |
| 2 | + |
| 3 | +import time |
| 4 | + |
| 5 | +from micropython import const |
| 6 | + |
| 7 | +import board |
| 8 | + |
| 9 | +import digitalio |
| 10 | +import neopixel_write |
| 11 | + |
| 12 | +from adafruit_ble import BLERadio |
| 13 | + |
| 14 | +import adafruit_apds9960.apds9960 |
| 15 | +import adafruit_bmp280 |
| 16 | +import adafruit_lsm6ds |
| 17 | +import adafruit_sht31d |
| 18 | + |
| 19 | +import audiobusio |
| 20 | + |
| 21 | +from adafruit_ble_adafruit.adafruit_service import AdafruitServerAdvertisement |
| 22 | + |
| 23 | +from adafruit_ble_adafruit.accelerometer_service import AccelerometerService |
| 24 | +from adafruit_ble_adafruit.addressable_pixel_service import AddressablePixelService |
| 25 | +from adafruit_ble_adafruit.barometric_pressure_service import BarometricPressureService |
| 26 | +from adafruit_ble_adafruit.button_service import ButtonService |
| 27 | +from adafruit_ble_adafruit.humidity_service import HumidityService |
| 28 | +from adafruit_ble_adafruit.light_sensor_service import LightSensorService |
| 29 | +from adafruit_ble_adafruit.microphone_service import MicrophoneService |
| 30 | +from adafruit_ble_adafruit.temperature_service import TemperatureService |
| 31 | + |
| 32 | +import ulab |
| 33 | + |
| 34 | +# Accelerometer |
| 35 | +lsm6ds33 = adafruit_lsm6ds.LSM6DS33(board.I2C()) |
| 36 | +# Used for pressure and temperature. |
| 37 | +bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(board.I2C()) |
| 38 | +# Humidity. |
| 39 | +sht31d = adafruit_sht31d.SHT31D(board.I2C()) |
| 40 | +# Used only for light sensor |
| 41 | +apds9960 = adafruit_apds9960.apds9960.APDS9960(board.I2C()) |
| 42 | +apds9960.enable_color = True |
| 43 | + |
| 44 | +mic = audiobusio.PDMIn( |
| 45 | + board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16, |
| 46 | +) |
| 47 | + |
| 48 | +accel_svc = AccelerometerService() |
| 49 | +accel_svc.measurement_period = 100 |
| 50 | +accel_last_update = 0 |
| 51 | + |
| 52 | +# One NeoPixel on the board. |
| 53 | +NEOPIXEL_BUF_LENGTH = const(3 * 1) |
| 54 | +neopixel_svc = AddressablePixelService() |
| 55 | +neopixel_buf = bytearray(NEOPIXEL_BUF_LENGTH) |
| 56 | +neopixel_out = digitalio.DigitalInOut(board.NEOPIXEL) |
| 57 | +neopixel_out.switch_to_output() |
| 58 | + |
| 59 | +baro_svc = BarometricPressureService() |
| 60 | +baro_svc.measurement_period = 100 |
| 61 | +baro_last_update = 0 |
| 62 | + |
| 63 | +button_svc = ButtonService() |
| 64 | +button = digitalio.DigitalInOut(board.SWITCH) |
| 65 | +button.pull = digitalio.Pull.UP |
| 66 | +button_svc.set_pressed(False, not button.value, False) |
| 67 | + |
| 68 | +humidity_svc = HumidityService() |
| 69 | +humidity_svc.measurement_period = 100 |
| 70 | +humidity_last_update = 0 |
| 71 | + |
| 72 | +light_svc = LightSensorService() |
| 73 | +light_svc.measurement_period = 100 |
| 74 | +light_last_update = 0 |
| 75 | + |
| 76 | +# Send 256 16-bit samples at a time. |
| 77 | +MIC_NUM_SAMPLES = const(256) |
| 78 | +mic_svc = MicrophoneService() |
| 79 | +mic_svc.number_of_channels = 1 |
| 80 | +mic_svc.measurement_period = 100 |
| 81 | +mic_last_update = 0 |
| 82 | +mic_samples = ulab.zeros(MIC_NUM_SAMPLES, dtype=ulab.uint16) |
| 83 | + |
| 84 | +temp_svc = TemperatureService() |
| 85 | +temp_svc.measurement_period = 100 |
| 86 | +temp_last_update = 0 |
| 87 | + |
| 88 | +ble = BLERadio() |
| 89 | +# The Web Bluetooth dashboard identifies known boards by their |
| 90 | +# advertised name, not by advertising manufacturer data. |
| 91 | +ble.name = "Sense" |
| 92 | + |
| 93 | +# The Bluefruit Playground app looks in the manufacturer data |
| 94 | +# in the advertisement. That data uses the USB PID as a unique ID. |
| 95 | +# Feather Bluefruit Sense USB PID: |
| 96 | +# This board is not yet support on the app. |
| 97 | +# Arduino: 0x8087, CircuitPython: 0x8088 |
| 98 | +adv = AdafruitServerAdvertisement(0x8088) |
| 99 | + |
| 100 | +while True: |
| 101 | + # Advertise when not connected. |
| 102 | + ble.start_advertising(adv) |
| 103 | + while not ble.connected: |
| 104 | + pass |
| 105 | + ble.stop_advertising() |
| 106 | + |
| 107 | + while ble.connected: |
| 108 | + now_msecs = time.monotonic_ns() // 1000000 # pylint: disable=no-member |
| 109 | + |
| 110 | + if now_msecs - accel_last_update >= accel_svc.measurement_period: |
| 111 | + accel_svc.acceleration = lsm6ds33.acceleration |
| 112 | + accel_last_update = now_msecs |
| 113 | + |
| 114 | + if now_msecs - baro_last_update >= baro_svc.measurement_period: |
| 115 | + baro_svc.pressure = bmp280.pressure |
| 116 | + baro_last_update = now_msecs |
| 117 | + |
| 118 | + button_svc.set_pressed(False, not button.value, False) |
| 119 | + |
| 120 | + if now_msecs - humidity_last_update >= humidity_svc.measurement_period: |
| 121 | + humidity_svc.humidity = sht31d.relative_humidity |
| 122 | + humidity_last_update = now_msecs |
| 123 | + |
| 124 | + if now_msecs - light_last_update >= light_svc.measurement_period: |
| 125 | + # Return "clear" color value from color sensor. |
| 126 | + light_svc.light_level = apds9960.color_data[3] |
| 127 | + light_last_update = now_msecs |
| 128 | + |
| 129 | + if now_msecs - mic_last_update >= mic_svc.measurement_period: |
| 130 | + mic.record(mic_samples, len(mic_samples)) |
| 131 | + # This subtraction yields unsigned values which are |
| 132 | + # reinterpreted as signed after passing. |
| 133 | + mic_svc.sound_samples = mic_samples - 32768 |
| 134 | + mic_last_update = now_msecs |
| 135 | + |
| 136 | + neopixel_values = neopixel_svc.values |
| 137 | + if neopixel_values is not None: |
| 138 | + start = neopixel_values.start |
| 139 | + if start > NEOPIXEL_BUF_LENGTH: |
| 140 | + continue |
| 141 | + data = neopixel_values.data |
| 142 | + data_len = min(len(data), NEOPIXEL_BUF_LENGTH - start) |
| 143 | + neopixel_buf[start : start + data_len] = data[:data_len] |
| 144 | + if neopixel_values.write_now: |
| 145 | + neopixel_write.neopixel_write(neopixel_out, neopixel_buf) |
| 146 | + |
| 147 | + if now_msecs - temp_last_update >= temp_svc.measurement_period: |
| 148 | + temp_svc.temperature = bmp280.temperature |
| 149 | + temp_last_update = now_msecs |
0 commit comments