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

Files at this revision

API Documentation at this revision

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            
     }