UltraV: Draagbare UV-Index Meter voor Veilige Zonnbelichting
Onderdelen en benodigdheden
| Arduino Nano R3 | Aantal: 1 |
| Texas Instruments ML-8511 UV-sensor | Aantal: 1 |
| 128x64 OLED-display (SSD1306) | Aantal: 1 |
| MT3608 DC-DC step-up converter | Aantal: 1 |
| CR2 (3V) batterij | Aantal: 1 |
| CR2 batterijhouder | Aantal: 1 |
Over dit project
Omdat ik mijn niet aan de zon kon blootstellen door een dermatologisch probleem, besteedde ik de tijd die ik anders op het strand had doorgebracht aan het bouwen van een ultraviolette-stralenmeter: de UltraV.
Het apparaat is gebouwd om een Arduino Nano rev3, met een UV-sensor, een DC/DC-converter om de 3V-batterijspanning op te voeren, en een klein OLED-display. Mijn hoofddoel was draagbaarheid: op elk moment en op elke plaats de UV-index kunnen aflezen.
Stap 1: Onderdelen
- Microcontroller Arduino Nano rev.3
- ML8511 UV-sensor
- 128×64 OLED-display (SSD1306)
- MT3608 DC-DC step-up converter
- CR2-batterij
- CR2-batterijhouder
- Schakelaar
- Behuizing
Stap 2: De sensor (ML8511)

De ML8511 (Lapis Semiconductors) is een UV-sensor geschikt voor binnen- en buitenshuis. De sensor heeft een ingebouwde operationele versterker die fotostroom omzet in spanning afhankelijk van de UV-intensiteit. Dit biedt een eenvoudige interface voor externe circuits zoals een ADC. In standby-modus is de stroomverbruik slechts 0,1 µA – ideaal voor lange batterijduur.
Kenmerken:
- Fotodiode gevoelig voor UV-A en UV-B
- Ingebouwde operationele versterker
- Analoge spanninguitgang
- Laag stroomverbruik (300 µA typ.) en lage standby-stroom (0,1 µA typ.)
- Klein SMD-behuizing (4,0 × 3,7 × 0,73 mm, 12-pin keramische QFN)

Let op: Ik kon geen UV-doorlatend materiaal vinden om de sensor te beschermen. Elke geteste afdekking (plastic, glas) dempt de UV-metingen. Kwarts glas zou ideaal zijn, maar was te duur. Ik besloot de sensor open in de lucht te monteren.
Stap 3: Bediening

Om te meten: schakel het apparaat in, richt het naar de zon voor enkele seconden (uitgelijnd met de zonnestralen), en lees het display af.
- Linkerwaarde (INSTANT): Directe meting (elke 200 ms).
- Rechterwaarde (MAXIMUM): Hoogste waarde tijdens deze sessie – dit is de waarde die je gebruikt.
- Linksonder (WHO-categorie): Laag, Matig, Hoog, Zeer hoog, Extreem – volgens WHO UV-index standaarden.
Stap 4: Batterijspanning en meting
Ik koos een CR2-batterij (800 mAh) omwille van formaat en capaciteit. Na een zomer lang gebruik meet de batterij nog 2,8 V – uitstekend. Het circuit trekt ~100 mA tijdens meting, maar een meting duurt slechts seconden. Omdat de nominale spanning 3V is, voegde ik een DC-DC step-up converter toe om de spanning naar 9V te brengen en op de Vin-pin aan te sluiten.
Voor batterijspanningsindicatie op het display gebruikte ik een analoge ingang (A2). Arduino analoge ingangen meten 0-5V, maar vereisen calibratie:
- Voed het circuit met de definitieve CR2-batterij (niet via USB).
- Meet de 5V op de Arduino 5V-pin (deze spanning is de ADC-referentie).
- Vul de gemeten waarde in de sketch in (voorbeeld: 5,023V):
voltage = ((long)sum / (long)NUM_SAMPLES * 5023) / 1024.0;
In de sketch wordt het gemiddelde over 10 samples genomen.
Stap 5: Schema en verbindingen

Stap 6: Software
Voor het display gebruik ik de U8g2lib, zeer flexibel en krachtig voor OLED-displays met veel fonts en positioneringsopties.
Voor de spanningsmeting van de ML8511 gebruik ik de 3,3V referentiepins van de Arduino (nauwkeurigheid binnen 1%) als basis voor de ADC. Door een ADC-conversie op de 3,3V-pin (aangesloten op A1) en deze te vergelijken met de sensorlezing, verkrijgen we een accurate meting ongeacht de VIN-spanning (mits > 3,4V).
int uvLevel = averageAnalogRead(UVOUT);
int refLevel = averageAnalogRead(REF_3V3);
float outputVoltage = 3.3 / refLevel * uvLevel;
Download de volledige code (UltraV_OLED.ino.zip)
Stap 7: Behuizing

Na mislukte pogingen een commercieel plastic doosje handmatig uit te zagen, ontwierp ik mijn eigen behuizing in CAD. Om het zo compact mogelijk te houden, monteerde ik de CR2-batterij extern aan de achterkant (batterijhouder gelijmd op de doos).
Download het STL-bestand voor de behuizing (UltraV.stl.zip)
Stap 8: Mogelijke toekomstige verbeteringen
- Een UV-spectrometer gebruiken om echte real-time UV-indexwaarden te meten onder diverse omstandigheden (zeer duur).
- Gelijktijdig de ML8511-output registreren met de Arduino.
- Algoritme schrijven om ML8511-output te relateren aan echte UVI-waarde in real-time onder diverse atmosferische condities.
Stap 9: Afbeeldingen






Stap 10: Credits
- Carlos Orts: Arduino Project Hub
- Arduino Forum: ADC calibratie discussie
- Starting Electronics: Artikelen
- U8g2lib: Referentie
- Wereldgezondheidsorganisatie, UV-index: WHO richtlijnen
Code
UltraV (C/C++)
/* Fabio Marzocca @ 2018
ADC-conversies zijn volledig afhankelijk van VCC. We nemen aan 5V, maar via USB kan dit 4,75-5,25V zijn.
Oplossing: gebruik de accurate onboard 3,3V referentie (binnen 1%).
Door ADC op 3,3V-pin (A1) te doen en te vergelijken met sensorlezing, krijgen we accurate meting ongeacht VIN (>3,4V).
v2.0.0 - Juli 2018 - van 16x2 LCD naar OLED
v2.0.1 - Sept 2018 - batterijleesfunctie gewijzigd */
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL, SDA, U8X8_PIN_NONE);
#define FIRST_ROW_Y 16
#define FIRST_ROW_X 16
#define BOX_H 38
const int UVOUT = A0;
const int REF_3V3 = A1;
const int VBATT = A2;
float maxUV = 0;
void setup() {
pinMode(UVOUT, INPUT);
pinMode(REF_3V3, INPUT);
pinMode(VBATT, INPUT);
u8g2.begin();
}
void loop() {
u8g2.firstPage();
do {
int uvLevel = averageAnalogRead(UVOUT);
int refLevel = averageAnalogRead(REF_3V3);
float outputVoltage = 3.3 / refLevel * uvLevel;
float uvIntensity = mapfloat(outputVoltage, 0.99, 2.6, 0.0, 15.0);
readBattery();
if (maxUV < uvIntensity) maxUV = uvIntensity;
u8g2.drawFrame(0, FIRST_ROW_Y+1, 128, BOX_H);
u8g2.setFont(u8g2_font_logisoso18_tf);
u8g2.setCursor(10, 40); u8g2.print(uvIntensity); // INSTANT
u8g2.setCursor(70, 40); u8g2.print(maxUV); // MAXIMUM
u8g2.setFont(u8g2_font_u8glib_4_tf);
u8g2.setCursor(10, 52); u8g2.print(F("INSTANT"));
u8g2.setCursor(75, 52); u8g2.print(F("MAXIMUM"));
showUVCategory();
u8g2.setCursor(88, 64); u8g2.print(F("F.Marzocca"));
} while (u8g2.nextPage());
delay(200);
}
void showUVCategory() {
char strCat[12];
byte categ = (byte)(maxUV + 0.5); // afronden
if (categ >= 0 && categ < 3) strcpy(strCat, "LOW");
else if (categ >= 3 && categ < 6) strcpy(strCat, "MODERATE");
else if (categ >= 6 && categ < 8) strcpy(strCat, "HIGH !");
else if (categ >= 8 && categ < 10) strcpy(strCat, "VERY HIGH!");
else if (categ >= 11) strcpy(strCat, "EXTREME!");
u8g2.setCursor(0, 64); u8g2.print(strCat);
}
int averageAnalogRead(int pinToRead) {
byte numberOfReadings = 16;
unsigned int runningValue = 0;
for (int 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;
}
void readBattery() {
long battery = readBattVcc();
long VccMin = 2300;
byte batteryBar;
int barStep = 140;
batteryBar = (battery - VccMin) / barStep;
u8g2.setFont(u8g2_font_open_iconic_embedded_2x_t);
u8g2.drawGlyph(1, FIRST_ROW_Y, 73); // batterij-icoon
u8g2.setFont(u8g2_font_open_iconic_play_1x_t);
for (byte i = 1; i <= batteryBar; i++) {
u8g2.drawGlyph(128 - 9*i, FIRST_ROW_Y - 4, 75); // vulling
}
u8g2.setFont(u8g2_font_freedoomr10_tu);
u8g2.setCursor(25, FIRST_ROW_Y);
u8g2.print(float(battery)/1000, 3); // spanning in V
}
long readBattVcc() {
int sum = 0, sample_count = 0;
long voltage = 0;
#define NUM_SAMPLES 10
while (sample_count < NUM_SAMPLES) {
sum += analogRead(VBATT);
sample_count++;
delay(2);
}
// 5020 mV = gecalibreerde referentiespanning voor dit project
voltage = ((long)sum / (long)NUM_SAMPLES * 5020) / 1024.0;
return voltage; // in millivolt
}
Productieproces
- Draagbare puntlasmachines: definitie, werking en voordelen
- Kiezen tussen vaste en draagbare CMM-meetmachines: Wat u moet weten
- De Essentiële Rol van Automotive Accu's: Uw Voertuig Voeden
- Hoe Uw Dynamo Te Testen: Expert Methodes voor Betrouwbare Resultaten
- 7 duidelijke signalen dat uw dynamo defect is
- Spanningsdeler Lab: Ontwerp, Meting en Verificatie van Kirchhoffs Spanningswet
- Een Aardappelbatterij Bouwen: Stapsgewijze Handleiding voor DIY Elektrochemische Energie
- Meetapparaatontwerp begrijpen: van klassieke galvanometers tot moderne digitale displays
- Multimeters: van analog naar digitaal – een uitgebreide gids
- Batterijconstructie fundamenteel: cellen, interne weerstand, en connectiviteit
- Batterijcapaciteit begrijpen: Ampère-uur waarden en conditietesten