UV-Sensoren mit Arduino

UV-Light der Sonne

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.

Verwendete Bauteile

Sensor: VEML6075

VEML6075 Sensor von Vishay Semiconductors
Abb.: VEML6075 Sensor von Vishay Semiconductors

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.

Technische Daten des Sensors

VEML6075-Modul
Abb.: VEML6075-Modul mit Pins für Stromversorgung und I²C-Schnittstelle

Anschlüsse und Aufbau

VEML6075 Arduino Uno
VCC 3V
GND GND
SCL A5
SDA A4

Sketch I. - Einfacher Test

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);
}
UV-Index: 0.00 UV-Index: 0.00 UV-Index: 0.05 UV-Index: 0.06 UV-Index: 0.06 UV-Index: 0.06 UV-Index: 0.06 UV-Index: 0.46 UV-Index: 0.44 UV-Index: 0.64 UV-Index: 0.71
Abb.: Messungen werden auf der seriellen Konsole ausgegeben:
- abgedeckter Sensor: "0.00"
- Zimmerbeleuchtung: "0.06"
- UV-Taschenlampe: >"0.46"

Sketch II. - Detaillierterer Test

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);
}
Raw UV-A: 0.00 Raw UV-B: 0.00 UV-Index: 0.00 Raw UV-A: 36.02 Raw UV-B: 43.45 UV-Index: 0.08 Raw UV-A: 225.11 Raw UV-B: 71.66 UV-Index: 0.26
Abb.: Detailliertere Messungen werden auf der seriellen Konsole ausgegeben: Hier wieder mit abgedecktem Sensor, Zimmerbeleuchtung und UV-Taschenlampe

Es gibt auch noch weitere Libraries, die ich bisher nicht ausprobiert habe, aber vom Funktionsumfang ähnlich sind:
- VEML6075
- SparkFun_VEML6075_Arduino_Library

Sensor: GY-8511 (ML8511)

ML8511 Sensor
Abb.: ML8511 Sensor

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.

Technische Daten des Sensors

ML8511-Modul
Abb.: ML8511-Modul

Anschlüsse und Aufbau

GY-8511 Arduino Uno
VIN 3,3V
3V3 A1
GND GND
OUT A0
EN ("Enable"; active HIGH) 3,3V

Sketch

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 recht 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;
}
ML8511 output: 202 MP8511 voltage: 0.98 UV-Intensity (mW/cm²): -0.11 ML8511 output: 235 MP8511 voltage: 1.14 UV-Intensity (mW/cm²): 1.14 ML8511 output: 294 MP8511 voltage: 1.42 UV-Intensity (mW/cm²): 3.38
Abb.: Die Messungen werden auf der seriellen Konsole ausgegeben: Hier wieder mit abgedecktem Sensor, Zimmerbeleuchtung und UV-Taschenlampe

Weitere Ideen/Möglichkeiten

zurück