Ultraviolet Intensity Measurement Experiment: Unterschied zwischen den Versionen
Dl8rds (Diskussion | Beiträge) (→Solution Concept) |
Dl8rds (Diskussion | Beiträge) |
||
(6 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 13: | Zeile 13: | ||
Here is a nice overview of sunburn effects: | Here is a nice overview of sunburn effects: | ||
− | [[Image:2017-07-31-sunburn1.png| | + | [[Image:2017-07-31-sunburn1.png|600px]] |
The sensor will display all measured values including a normalization on a web page. I am also interested in other environmental data (is the sensor doing fine?), so I decided to use a BME280 sensor also. | The sensor will display all measured values including a normalization on a web page. I am also interested in other environmental data (is the sensor doing fine?), so I decided to use a BME280 sensor also. | ||
Zeile 21: | Zeile 21: | ||
Here is the rough output scale of the sensor: | Here is the rough output scale of the sensor: | ||
− | [[Image:2017-07-31-UV_intensity_ml8511.png| | + | [[Image:2017-07-31-UV_intensity_ml8511.png|600px]] |
== Component List == | == Component List == | ||
Zeile 27: | Zeile 27: | ||
* Hammond 1550E aluminium diecast case: 50 € | * Hammond 1550E aluminium diecast case: 50 € | ||
* 2sided base PCB: 2 € | * 2sided base PCB: 2 € | ||
− | * Arduino Ethernet: | + | * Arduino Ethernet: 65 € |
+ | : http://vampiresquidlabs.com/cms/shop/arduino-uno-ethernet/ | ||
* Programmer: 3 € | * Programmer: 3 € | ||
* Watterott BME280: 14 € | * Watterott BME280: 14 € | ||
Zeile 49: | Zeile 50: | ||
* TP-Link PoE injector: 25 | * TP-Link PoE injector: 25 | ||
− | Total: | + | Total: ~400 € |
== Code == | == Code == | ||
Zeile 247: | Zeile 248: | ||
</pre> | </pre> | ||
− | Sample Output | + | == Sample Output == |
+ | |||
+ | Here is a sample output from this evening, notably with no UV rays at all. The next days will be very sunny, so I'm looking forward to read the measurements. | ||
<pre> | <pre> | ||
Zeile 259: | Zeile 262: | ||
Temperature (C) 27.26 | Temperature (C) 27.26 | ||
</pre> | </pre> | ||
+ | |||
+ | == Images == | ||
+ | |||
+ | [[Image:2017-07-31-UV-Sensor1.jpg|400px]] | ||
+ | [[Image:2017-07-31-UV-Sensor3.jpg|400px]] | ||
+ | |||
+ | [[Image:2017-07-31-UV-Sensor2.jpg|400px]] | ||
+ | [[Image:2017-07-31-UV-Sensor4.jpg|400px]] | ||
+ | |||
+ | [[Image:2017-07-31-UV-Sensor5.jpg|400px]] | ||
+ | [[Image:2017-07-31-UV-Sensor6.jpg|400px]] | ||
+ | |||
+ | [[Image:2017-07-31-UV-Sensor7.jpg|600px]] |
Aktuelle Version vom 8. August 2017, 23:03 Uhr
Inhaltsverzeichnis
1 Project Scope
When my daughter (my first child) was still a baby, my father bought a UV sensor so he could measure the UV intensity. Babys are very sensitive to UV light and the worst thing he could image was a baby sunburn.
So I thought, what about creating an alarm sensor that would measure UV intensity continuously. The result is this experiment, years later but no less outdated.
2 Solution Concept
I decided to build up the entire solution on the basis of a PoE 803.af Arduino Ethernet, including measurement of environment data and ambient light, including a solar cell based voltage verification.
There are pairs of ML8511 sensors, one pair simply behind the SiO (Silicium Oxide / Quarz glass), and another pair behind a lowpass UVB filter so that these two can measure exclusively UV-A. The UVB intensity is then the difference between the tutal power in this spectral region minus the UVA.
Here is a nice overview of sunburn effects:
The sensor will display all measured values including a normalization on a web page. I am also interested in other environmental data (is the sensor doing fine?), so I decided to use a BME280 sensor also.
The ADS1115 has a programmable sensitivity feature, and the ML8511 runs on 3,3V. So I decided to use this 16 bit ADC on a Vmax basis of 4,096V, since the signal will not exceed 3,3V anyway. 3,28V is Vmax according to the sensor's spec and it will correlate with a brutal amount of 15mW/cm².
Here is the rough output scale of the sensor:
3 Component List
- Hammond 1550E aluminium diecast case: 50 €
- 2sided base PCB: 2 €
- Arduino Ethernet: 65 €
- Programmer: 3 €
- Watterott BME280: 14 €
- 4x Sparkfun ML8511: 4x 15€ = 60 €
- 1x Sparkfun TEMT6000: 5 €
- https://www.sparkfun.com/products/8688
- https://learn.sparkfun.com/tutorials/temt6000-ambient-light-sensor-hookup-guide
- Adafruit ADS1115: 15 €
- 2 solar cells: 5 €
- screws, mounts: 10 €
- Edmund Optics UVB lowpass: 80 €
- Cut-Off Position λc (nm): 309±6
- https://www.edmundoptics.com/optics/optical-filters/longpass-edge-filters/n-wg-305-50.8mm-sq.-longpass-filter/
- Quarz glass to pass all wavelengths: 65 €
- Silicon glue: 10 €
- TP-Link PoE injector: 25
Total: ~400 €
4 Code
#include <SPI.h> #include <Ethernet.h> #include <Wire.h> #include <Adafruit_ADS1015.h> #include "cactus_io_BME280_I2C.h" Adafruit_ADS1115 ads; /* Use this for the 16-bit version */ // Create the BME280 object BME280_I2C bme; // I2C using default 0x77 // or BME280_I2C bme(0x76); // I2C using address 0x76 // Enter a MAC address and IP address for your controller below. // The IP address will be dependent on your local network: byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 178, 177); // Initialize the Ethernet server library // with the IP address and port you want to use // (port 80 is default for HTTP): EthernetServer server(80); void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); // The ADC input range (or gain) can be changed via the following // functions, but be careful never to exceed VDD +0.3V max, or to // exceed the upper and lower limits if you adjust the input range! // Setting these values incorrectly may destroy your ADC! // ADS1015 ADS1115 // ------- ------- // ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default) ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV // ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV // ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV // ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV // ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV ads.begin(); if (!bme.begin()) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1); } bme.setTempCal(-1); } //The Arduino Map function but for floats //From: http://forum.arduino.cc/index.php?topic=3922.0 float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("new client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println("Refresh: 5"); // refresh the page automatically every 5 sec client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<table>"); client.print("<tr><td>"); client.print("Light Intensity:"); client.print("</td><td>"); int sensorReading = analogRead(0); Serial.print("Light Intensity: "); Serial.println(sensorReading); client.print(sensorReading); client.println("</td></tr>"); int16_t adc0, adc1, adc2, adc3; float adc0_1, adc1_1, adc2_1, adc3_1; float uvIntensity_0, uvIntensity_1, uvIntensity_2, uvIntensity_3; client.print("<tr><td>"); client.print("UVB1 (mW/cm2):"); client.print("</td><td>"); adc0 = ads.readADC_SingleEnded(0); adc0_1 = (float)adc0 / 8000; uvIntensity_0 = mapfloat(adc0_1, 0.987, 2.8, 0.0, 15.0); Serial.print("UVB1: "); Serial.println(uvIntensity_0); client.print(uvIntensity_0); client.println("</td></tr>"); client.print("<tr><td>"); client.print("UVB2 (mW/cm2):"); client.print("</td><td>"); adc1 = ads.readADC_SingleEnded(1); adc1_1 = (float)adc1 / 8000; uvIntensity_1 = mapfloat(adc1_1, 0.999, 2.8, 0.0, 15.0); Serial.print("UVB2: "); Serial.println(uvIntensity_1); client.print(uvIntensity_1); client.println("</td></tr>"); client.print("<tr><td>"); client.print("UV1 (mW/cm2):"); client.print("</td><td>"); adc2 = ads.readADC_SingleEnded(2); adc2_1 = (float)adc2 / 8000; uvIntensity_2 = mapfloat(adc2_1, 0.989, 2.8, 0.0, 15.0); Serial.print("UV1: "); Serial.println(uvIntensity_2); client.print(uvIntensity_2); client.println("</td></tr>"); client.print("<tr><td>"); client.print("UV2 (mW/cm2):"); client.print("</td><td>"); adc3 = ads.readADC_SingleEnded(3); adc3_1 = (float)adc3 / 8000; uvIntensity_3 = mapfloat(adc3_1, 0.999, 2.8, 0.0, 15.0); Serial.print("UV2: "); Serial.println(uvIntensity_3); client.print(uvIntensity_3); client.println("</td></tr>"); bme.readSensor(); client.print("<tr><td>"); client.print("Pressure (millibar)"); client.print("</td><td>"); Serial.print("Pressure (millibar): "); Serial.println(bme.getPressure_MB()); client.print(bme.getPressure_MB()); client.println("</td></tr>"); client.print("<tr><td>"); client.print("Humidity (%rel)"); client.print("</td><td>"); Serial.print("Humidity (%rel): "); Serial.println(bme.getHumidity()); client.print(bme.getHumidity()); client.println("</td></tr>"); client.print("<tr><td>"); client.print("Temperature (C)"); client.print("</td><td>"); Serial.print("Temperature (C): "); Serial.println(bme.getTemperature_C()); client.print(bme.getTemperature_C()); client.println("</td></tr>"); client.println("</table>"); client.println("</html>"); break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); Serial.println("client disconnected"); } }
5 Sample Output
Here is a sample output from this evening, notably with no UV rays at all. The next days will be very sunny, so I'm looking forward to read the measurements.
Light Intensity: 285 UVB1 (mW/cm2): 0.02 UVB2 (mW/cm2): 0.02 UV1 (mW/cm2): 0.02 UV2 (mW/cm2): 0.02 Pressure (millibar) 957.97 Humidity (%rel) 58.39 Temperature (C) 27.26