Arduino Nano ESP32 - GUVA-S12SD UV Sensor

In this guide, we will learn how to use the GUVA-S12SD UV sensor with the Arduino Nano ESP32. Your eyes cannot see ultraviolet light, but your skin feels it a few hours later. This small module gives the Nano ESP32 a way to "see" it, and because the board has WiFi, the number can later go to your phone or a web page. In detail, we will learn:

Arduino Nano ESP32 and GUVA-S12SD UV sensor module

Hardware Preparation

1×Arduino Nano ESP32
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×GUVA-S12SD UV Sensor Module
1×Jumper Wires
1×Breadboard
1×Optionally, DC Power Jack
1×Recommended: Screw Terminal Expansion Board for Arduino Nano
1×Recommended: Breakout Expansion Board for Arduino Nano
1×Recommended: Power Splitter for Arduino Nano ESP32

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of GUVA-S12SD UV Sensor

The module is a tiny purple board, about 11mm x 27mm, with a mounting hole at each end. The part that does the work is the little white square: a GUVA-S12SD UV photodiode. Next to it sits a VLM358 op-amp chip. The DIYables version comes in a pack of two, with the pin header already soldered.

GUVA-S12SD UV sensor module pinout
image source: diyables.io

How does it work? When UV light lands on the photodiode, it lets a very small current flow. That current is far too weak to measure directly, so the op-amp turns it into a voltage on the SIG pin. More UV gives a higher voltage. The Nano ESP32 then only has to read that voltage on an analog pin.

Main facts:

  • Light it reacts to: UV-A and UV-B, 240nm to 370nm
  • Viewing angle: 130 degrees
  • Supply: 2.5V to 5V DC
  • Output: analog voltage, near 0V with no UV, around 1V or a bit more in strong summer sun

The header has three pins. Read them on the board from one side: SIG, GND, VCC.

  • SIG pin: the analog output. Connect it to A0 of the Nano ESP32.
  • GND pin: connect to GND (0V).
  • VCC pin: connect to the 3V3 pin. The module accepts up to 5V, but the Nano ESP32 is a 3.3V board, so keep the sensor at 3.3V too.

A good thing to know before you start: room lights, phone screens and even a bright window give almost no UV. So indoors the module reads close to 0, and that is normal, not a fault. Take it outside into the sun, or shine a UV flashlight on it, to see real numbers.

From voltage to UV index

The UV index is the number you see in weather apps. A simple rule used by many makers is:

UV index ≈ SIG voltage (V) / 0.1

So every 0.1V on SIG counts as about one UV index point. For example, 0.45V means a UV index of about 4.5. This is a rough value for hobby projects, not a calibrated UV meter. The World Health Organization groups the UV index like this:

UV Index Level What it means for you
0 - 2 Low Safe for most people
3 - 5 Moderate Wear a hat and sunscreen at midday
6 - 7 High Cover up and look for shade
8 - 10 Very High Stay out of the midday sun
11+ Extreme Avoid the sun when you can

Some ideas for this module with the Nano ESP32: a sunscreen reminder that sends a message to your phone, a small UV index station on the balcony, a tester that tells you whether a UV lamp or UV LED still works, a weather station on the roof, or a smart blind that closes when the sun gets too strong.

Wiring Diagram

Three wires are enough, no resistor and no breadboard: SIG to A0, GND to GND, and VCC to 3V3. A0 is a good choice on this board. Pins A0 to A3 belong to ADC1 of the ESP32-S3 chip, and ADC1 keeps working while WiFi is on, so you can add WiFi to this project later without moving the wire.

The wiring diagram between Arduino Nano ESP32 and GUVA-S12SD UV sensor

This image is created using Fritzing. Click to enlarge image

Wiring table of GUVA-S12SD UV Sensor and Arduino Nano ESP32

GUVA-S12SD UV Sensor Arduino Nano ESP32
SIG → A0
GND → GND
VCC → 3V3 (not VBUS)

How To Program For GUVA-S12SD UV Sensor

No library is needed. Everything comes with the Arduino core for the Nano ESP32.

  • Give the analog pin a name:
#define UV_SIG_PIN A0
  • In setup(), set the input range of the ADC to about 0V - 3.1V:
analogSetAttenuation(ADC_11db);
  • Read the raw ADC number. On the Nano ESP32 it goes from 0 to 4095 (12 bits):
int raw = analogRead(UV_SIG_PIN);
  • Read the voltage in millivolts. analogReadMilliVolts() uses the calibration data stored inside the ESP32-S3 chip, so it is more correct than doing the math on the raw number yourself:
float voltage = analogReadMilliVolts(UV_SIG_PIN) / 1000.0; // volts
  • Get the approximate UV index:
float uv_index = voltage / 0.1;

Arduino Nano ESP32 Code - Raw ADC Value and SIG Voltage

This first sketch is a check that the sensor is alive. Once per second it prints the raw ADC number and, next to it, the calibrated voltage in millivolts and volts. Seeing both side by side shows you why the calibrated value is the one to trust.

/* * This Arduino Nano ESP32 code was developed by newbiely.com * * This Arduino Nano ESP32 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-guva-s12sd-uv-sensor */ #define UV_SIG_PIN A0 // The Arduino Nano ESP32 pin connected to the SIG pin of the GUVA-S12SD module void setup() { Serial.begin(9600); // let the analog pin measure up to about 3.1V (the sensor output stays far below that) analogSetAttenuation(ADC_11db); } void loop() { int raw = analogRead(UV_SIG_PIN); // 12-bit value: 0 to 4095 int sig_mv = analogReadMilliVolts(UV_SIG_PIN); // calibrated voltage on the pin, in millivolts float sig_volt = sig_mv / 1000.0; // millivolts -> volts Serial.print("ADC raw: "); Serial.print(raw); Serial.print(" | SIG: "); Serial.print(sig_mv); Serial.print(" mV ("); Serial.print(sig_volt, 3); Serial.println(" V)"); delay(1000); // one line per second }

Detailed Instructions

Follow these instructions step by step:

  • If this is the first time you use Arduino Nano ESP32, see how to setup environment for Arduino Nano ESP32 on Arduino IDE.
  • Connect SIG, GND and VCC as listed in the wiring table. VCC goes to 3V3.
  • Plug the Arduino Nano ESP32 into your computer with a USB Type-C cable.
  • Launch the Arduino IDE on your computer.
  • Select the appropriate Arduino Nano ESP32 board (e.g., Arduino Nano ESP32) and COM port.
  • Paste the code above into a new sketch and click Upload.
  • Open the Serial Monitor at 9600 baud.
  • Look at the numbers on your desk first. Then carry the laptop and board to a sunny window that is open, or outside, and point the white sensor at the sky.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Nano ESP32
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Nano ESP32' on 'COM15')
New Line
9600 baud
ADC raw: 0 | SIG: 9 mV (0.009 V) ADC raw: 3 | SIG: 11 mV (0.011 V) ADC raw: 0 | SIG: 9 mV (0.009 V) ADC raw: 2 | SIG: 10 mV (0.010 V) ADC raw: 341 | SIG: 287 mV (0.287 V) ADC raw: 562 | SIG: 463 mV (0.463 V) ADC raw: 589 | SIG: 484 mV (0.484 V) ADC raw: 571 | SIG: 470 mV (0.470 V) ADC raw: 603 | SIG: 495 mV (0.495 V)
Ln 11, Col 1
Arduino Nano ESP32 on COM15
2

The first lines come from indoors: a few millivolts and nothing more. The jump happens when the board meets real sunlight. Notice that the raw number is not simply the voltage times a fixed factor. The ESP32-S3 ADC is not perfectly straight, which is why this tutorial uses analogReadMilliVolts() for every calculation.

※ NOTE THAT:

Closed glass windows block most UV-B and part of UV-A. If the reading stays low behind a window on a sunny day, open it or go outside.

Arduino Nano ESP32 Code - UV Index and Level

Now let's make the number useful. This sketch takes 16 calibrated readings, averages them so the value does not jump around, divides the voltage by 0.1 to get the UV index with one decimal, and adds the WHO level name.

/* * This Arduino Nano ESP32 code was developed by newbiely.com * * This Arduino Nano ESP32 code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-guva-s12sd-uv-sensor */ #define UV_SIG_PIN A0 // The Arduino Nano ESP32 pin connected to the SIG pin of the GUVA-S12SD module #define SAMPLE_COUNT 16 // how many readings are averaged for one result #define VOLT_PER_UVI 0.1 // rough rule: every 0.1V on SIG is about 1 UV index point // average several calibrated readings to calm down the noise of the ADC float readUVVoltage() { long sum_mv = 0; for (int i = 0; i < SAMPLE_COUNT; i++) { sum_mv += analogReadMilliVolts(UV_SIG_PIN); delay(5); } return (sum_mv / (float)SAMPLE_COUNT) / 1000.0; // average, in volts } // turn a UV index number into the WHO level name const char* uvLevel(float uv_index) { if (uv_index < 3) return "Low"; if (uv_index < 6) return "Moderate"; if (uv_index < 8) return "High"; if (uv_index < 11) return "Very High"; return "Extreme"; } void setup() { Serial.begin(9600); analogSetAttenuation(ADC_11db); // read up to about 3.1V on the analog pin } void loop() { float voltage = readUVVoltage(); float uv_index = voltage / VOLT_PER_UVI; // approximate value, not a calibrated meter Serial.print("SIG: "); Serial.print(voltage, 2); Serial.print(" V -> UV index: "); Serial.print(uv_index, 1); Serial.print(" ("); Serial.print(uvLevel(uv_index)); Serial.println(")"); delay(1000); }

Detailed Instructions

  • Keep the same wiring.
  • Paste the code above into the Arduino IDE and click Upload.
  • Open the Serial Monitor at 9600 baud.
  • Start in the shade, then move the sensor into direct sun around midday.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Nano ESP32
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Nano ESP32' on 'COM15')
New Line
9600 baud
SIG: 0.01 V -> UV index: 0.1 (Low) SIG: 0.01 V -> UV index: 0.1 (Low) SIG: 0.19 V -> UV index: 1.9 (Low) SIG: 0.36 V -> UV index: 3.6 (Moderate) SIG: 0.58 V -> UV index: 5.8 (Moderate) SIG: 0.66 V -> UV index: 6.6 (High) SIG: 0.67 V -> UV index: 6.7 (High) SIG: 0.65 V -> UV index: 6.5 (High)
Ln 11, Col 1
Arduino Nano ESP32 on COM15
2

Compare the result with the UV index in a weather app for your city. If your module always reads a little higher or lower, change VOLT_PER_UVI in the code (for example 0.11 or 0.09) until the two match. A small step further: use the WiFi of the Nano ESP32 to send a warning when the level reaches High.

※ NOTE THAT:

The Arduino Nano ESP32's ADC is fine for a hobby UV meter, but it is not a lab tool. Very small voltages (below about 50mV) are the least exact part of its range. If you need better precision, use an external ADC such as the ADS1115 module.

Video Tutorial

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!