This project can be used to measure UV light levels. It uses an ML8511 UV sensors and outputs its value over BLE in units of mW/cm^2
Revision 1:ab9f0e572c98, committed 2020-08-27
- Comitter:
- f3d
- Date:
- Thu Aug 27 12:42:55 2020 +0000
- Parent:
- 0:6d4b6c56a7ad
- Commit message:
- Initial commit
Changed in this revision
UVSensor.h | Show annotated file Show diff for this revision Revisions of this file |
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 6d4b6c56a7ad -r ab9f0e572c98 UVSensor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UVSensor.h Thu Aug 27 12:42:55 2020 +0000 @@ -0,0 +1,51 @@ +#ifndef __UVSENSOR_H +#define __UVSENSOR_H +#include <mbed.h> +#include <BLE.h> +AnalogIn UVSignalIn(P0_28); + +class UVService { +public: + const static uint16_t UV_SERVICE_UUID = 0xA012; + const static uint16_t UV_CHARACTERISTIC_UUID = 0xA013; + + UVService(BLE &_ble, int16_t initialUVValue) : + ble(_ble), UVValue(UV_CHARACTERISTIC_UUID, &initialUVValue) + { + GattCharacteristic *charTable[] = {&UVValue}; + GattService uvservice(UV_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); + ble.addService(uvservice); + } + + GattAttribute::Handle_t getValueHandle() const { + return UVValue.getValueHandle(); + } + void updateUVValue(uint16_t newValue) { + ble.gattServer().write(UVValue.getValueHandle(), (uint8_t *)&newValue, sizeof(uint16_t)); + } + + void poll() + { + uint16_t ADCIn = UVSignalIn.read_u16(); + // Need to scale this to mW/cm^2 + // To convert to a voltage : * 3.6/4095 + // To convert voltage to mW/cm^2 see page 8 of datasheet for ML8511 sensor + // This graph is for 3.0V, but the supply in this example is 3.3V. + // I'm ASSUMING that the device output is not a function of voltage supply (within reason) + // From Graph : UV power / area is roughly given by: + // Power = (Voltage - 1) * 7; + // Need to avoid unsigned overflow + // An input of 1V should give an ADC Value of (1/3.6)*4095 = 1137.5 (1138) + if (ADCIn >= 1137 ) + ADCIn = ADCIn - 1137; + else + ADCIn = 0; + ADCIn = ADCIn / 163; // 4095 / (7*3.6) = 163 + updateUVValue(ADCIn); + } +private: + BLE &ble; + ReadOnlyGattCharacteristic<int16_t> UVValue; + +}; +#endif \ No newline at end of file
diff -r 6d4b6c56a7ad -r ab9f0e572c98 main.cpp --- a/main.cpp Sat Aug 22 15:21:53 2020 +0000 +++ b/main.cpp Thu Aug 27 12:42:55 2020 +0000 @@ -15,22 +15,25 @@ */ #include "mbed.h" +#include "UVSensor.h" -#include "ble/services/iBeacon.h" +#include <BLE.h> BLE ble; + const static char DEVICE_NAME[] = "NRF52832"; -static const uint16_t uuid16_list[] = {0xabcd,0x1234}; +static const uint16_t uuid16_list[] = {UVService::UV_SERVICE_UUID}; DigitalOut Led(P0_25); Ticker ticker; +UVService *UVServicePtr; void periodicCallback(void) { + UVServicePtr->poll(); if (Led == 0) Led = 1; else Led = 0; - } /** @@ -81,6 +84,8 @@ ble.gap().onDisconnection(disconnectionCallback); ble.gattServer().onDataWritten(onDataWrittenCallback); ble.gattServer().onDataRead(onDataReadCallback); + uint16_t initial_value = 0; + UVServicePtr = new UVService(ble,initial_value); /* setup advertising */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); @@ -92,12 +97,11 @@ } int main(void) { - ticker.attach(periodicCallback, 0.1); /* Poll devices every 100ms */ - ble.init(bleInitComplete); - + ble.init(bleInitComplete); /* SpinWait for initialization to complete. This is necessary because the * BLE object is used in the main loop below. */ while (!ble.hasInitialized()) { /* spin loop */ } + ticker.attach(periodicCallback, 0.1); /* Poll devices every 100ms */ while (true) { ble.waitForEvent(); // allows or low power operation }