Das Licht der Sonne sendet neben dem sichtbaren Licht (zwischen 400nm und 700nm Wellenlänge) auch
Ultraviolettes (UV) Licht
aus, welches vom menschlichen Auge nicht mehr wahrgenommen werden kann.
(380nm ist die Empfindlichkeitsgrenze des menschlichen Auges)
Das Spektrum, in dem UV-Licht strahlt, ist gewöhnlich zwischen 380nm und 100nm, wobei es darüber hinaus
noch den Frequenzbereich des extremen UV-Lichtes (EUV) bei 10nm gibt.
Das UV-Licht wird auch in die Unterbereiche UV-A (380–315 nm), UV-B (315–280 nm) und UV-C (280–100 nm) eingeteilt.
Eine Besonderheit ist der sogenannte UV-Index,
welcher die Wirkung der UV-Strahlung der Sonne auf den menschlichen Körper widergeben soll.
Der erste hier getestete Sensor ist der VEML6075 von Vishay Semiconductors, ein CMOS-Chip, der UV-B und UV-B misst und die Werte über eine I²C-Schnittstelle bereitstellt. Da der Sensor nur als SMD-Bauteil vertrieben wird, ist es praktisch auf das gleichnamige Modul zurückzugreifen, v.a. wenn man mit einem Breadboard Versuche durchführen will oder Prototypen baut.
VEML6075 | Arduino Uno |
---|---|
VCC | 3V |
GND | GND |
SCL | A5 |
SDA | A4 |
Der folgende Sketch verwendet die Library Adafruit_VEML6075 und gibt den aktuell gemessenen UV-Index auf der seriellen Konsole des Arduino aus:
#include <Wire.h>
#include "Adafruit_VEML6075.h"
Adafruit_VEML6075 uv = Adafruit_VEML6075();
void setup()
{
Serial.begin(9600);
uv.begin();
}
void loop()
{
Serial.println("UV-Index: " + String(uv.readUVI()));
delay(1000);
}
Mit derselben Library wird nun ein detaillierterer Test durchgeführt, wobei die Messung in UV-A-
und UV-B-Strahlung aufgeteilt ist. Hier werden auch nach der Initialisierung verschiedene Funktionen
benutzt:
setIntegrationTime()
legt fest, wie oft die UV-Messwerte gelesen werden,
setHighDynamic(true)
hierbei werden die Messwerte im high dynamic-Modus ausgelesen,
setForcedMode(false)
die Messwerte werden ununterbrochen gelesen,
setCoefficients()
setzt die Berechnungskoeffizienten für den UV-Index.
Für mehr Details am Besten die Dokumentation bzw. den Code der Library einsehen.
#include <Wire.h>
#include "Adafruit_VEML6075.h"
Adafruit_VEML6075 uv = Adafruit_VEML6075();
void setup()
{
Serial.begin(9600);
uv.begin();
// Set the integration constant:
//VEML6075_50MS, VEML6075_100MS, VEML6075_200MS, VEML6075_400MS, VEML6075_800MS
uv.setIntegrationTime(VEML6075_100MS);;
// Set the high dynamic mode
uv.setHighDynamic(true);
// Set the mode
uv.setForcedMode(false);
// Set the calibration coefficients
uv.setCoefficients(2.22, 1.33, 2.95, 1.74, 0.001461, 0.002591);
}
void loop()
{
Serial.println("Raw UV-A: " + String(uv.readUVA()));
Serial.println("Raw UV-B: " + String(uv.readUVB()));
Serial.println("UV-Index: " + String(uv.readUVI()) + "\n\n");
delay(3000);
}
Es gibt auch noch weitere Libraries, die ich bisher nicht ausprobiert habe, aber vom Funktionsumfang ähnlich sind:
- VEML6075
- SparkFun_VEML6075_Arduino_Library
Der Sensor ML8511 gibt eine analoge Spannung aus, die linear von der gemessenen UV-Intensität (mW/cm²) abhängig ist.
Da der Arduino mit seinem ADC (Analog-Wandler) Spannungen zwischen 0V bis 5V messen kann, ist es recht einfach die
UV-Intensität zu ermitteln. Seine höchste Empfindlichkeit hat der ML8511 im Bereich von 280nm bis 390nm.
Im folgenden Experiment wird ebenfalls wieder ein Modul verwendet, um leichter auf einem Breadboard verbaut werden
zu können. Der Sensor selbst hat eine Betriebsspannung von 2,7V bis 3,3V, aber viele Module (wie das hier verwendete)
können auch mit 5V betrieben werden.
GY-8511 | Arduino Uno |
---|---|
VIN | 3,3V |
3V3 | A1 |
GND | GND |
OUT | A0 |
EN ("Enable"; active HIGH) | 3,3V |
In diesem Sketch wird ein kleiner Trick verwendet: Analog-Digital-Wandlungen basieren normalerweise auf VCC. Wenn also das Board per USB gespeist wird, können wir von einer Spannung von 4,75V bis 5,25V ausgehen. Aufgrund dieses Bereichs ist die Referenzspannung recht ungenau. Um dies zu beheben, wird hier die recht genaue interne 3,3V-Referenz (mit 1%ger Toleranz) verwendet. Der 3,3V-Pin wird also mit einem analogen Pin des Arduino (hier: A1) verbunden und die gelesenen Daten des Sensors anhand dieser Spannung extrapoliert (unabhängig von VIN).
#define UV_OUT A0
#define REF_3V3 A1
void setup()
{
Serial.begin(9600);
pinMode(UV_OUT, INPUT);
pinMode(REF_3V3, INPUT);
}
void loop()
{
int uvLevel = averageAnalogRead(UV_OUT);
int refLevel = averageAnalogRead(REF_3V3);
float outputVoltage = 3.3 / refLevel * uvLevel;
float uvIntensity = mapfloat(outputVoltage, 0.99, 2.9, 0.0, 15.0);
Serial.println("ML8511 output: " + String(uvLevel));
Serial.println("MP8511 voltage: " + String(outputVoltage));
Serial.println("UV-Intensity (mW/cm²): " + String(uvIntensity) + "\n\n");
delay(3000);
}
int averageAnalogRead(int pinToRead)
{
const byte numberOfReadings = 8;
unsigned int runningValue = 0;
for (byte x = 0 ; x < numberOfReadings ; x++) {
runningValue += analogRead(pinToRead);
}
runningValue /= numberOfReadings;
return (runningValue);
}
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;
}