How to Make a UV Sensor With OLED Screen Display

by lobster_enthusiast in Circuits > Arduino

48 Views, 0 Favorites, 0 Comments

How to Make a UV Sensor With OLED Screen Display

IMG_9109.jpg

This project will detect the UV level and display it on a little OLED display screen. the circuit is small, and perfect to adapt into a little keychain to take around (which i'm working on). i made this because i rarely put on sunscreen despite the high UV levels around, especially during summer, so i'm hoping that this device will help me put on sunscreen more often

Supplies

electronics needed:

  1. Arduino nano (another microcontroller could work too, like Uno)
  2. button (optional just to turn on and off)
  3. I2C OLED display screen, 0.96'' by 0.96''
  4. UV sensor GUVA-S12SD
  5. breadboard
  6. jumpers

Electronics Wiring

Screenshot 2026-07-25 at 11.01.57 PM.png
button wiring.png

Both the UV sensor and the oled display are powered by the 5V pin on the Nano, and have shared ground. Connect the signal (SIG) pin on the UV sensor to A0, SCL to A5 and SDA to A4 (A4 and A5 pins on the nano are capable of I2C, so can control the oled display).

optionally you could add a button to turn the display and sensor on and off, which you would connect it across gnd and a digital pin (i.e. D2)

Upload Arduino Code + Drawing Bitmaps

Screenshot 2026-07-25 at 11.17.08 PM.png

below is the code i used (no button logic), which includes the cloudy and sunny drawings i drew as bitmaps.

if you want to use your own drawings, you can draw them in this website which will generate a bitmap of the drawing, which you can just replace in the code: https://oled-pixel-editor.netlify.app/


#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 64

#define OLED_RESET -1

#define SCREEN_ADDRESS 0x3C


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


#define UV_PIN A0 //uv sensor pin


const float VREF = 5.0;


#define ICON_WIDTH 32

#define ICON_HEIGHT 32


// sun 32x32 bits

const unsigned char sunBitmap[] PROGMEM = {

0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x01, 0x40,

0x10, 0x00, 0x03, 0x80,

0x00, 0x00, 0x81, 0x00,

0x00, 0x00, 0x80, 0x02,

0x02, 0x00, 0x80, 0x20,

0x01, 0x00, 0x80, 0x40,

0x00, 0x80, 0x00, 0x80,

0x00, 0x43, 0xE1, 0x00,

0x00, 0x0F, 0xF8, 0x00,

0x00, 0x1F, 0xFC, 0x00,

0x00, 0x3F, 0xFE, 0x00,

0x00, 0x3F, 0xFE, 0x00,

0x00, 0x7F, 0xFF, 0x00,

0x00, 0x7F, 0xFF, 0x00,

0x0F, 0x7F, 0xFF, 0x78,

0x00, 0x7F, 0xFF, 0x00,

0x00, 0x7F, 0xFF, 0x00,

0x00, 0x3F, 0xFE, 0x00,

0x40, 0x3F, 0xFE, 0x00,

0x00, 0x1F, 0xFC, 0x00,

0x00, 0x4F, 0xF9, 0x00,

0x00, 0x83, 0xE0, 0x80,

0x01, 0x00, 0x00, 0x40,

0x02, 0x00, 0x80, 0x20,

0x00, 0x00, 0x80, 0x00,

0x00, 0x00, 0x80, 0x00,

0x00, 0x00, 0x80, 0x00,

0x01, 0x00, 0x80, 0x00,

0x03, 0x80, 0x00, 0x08,

0x09, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00

};


// cloud 32x32 bits

const unsigned char cloudBitmap[] PROGMEM = {

0x00, 0x00, 0x00, 0x07,

0x0E, 0x08, 0x00, 0x0F,

0x1F, 0x80, 0x00, 0x1F,

0x7F, 0xF0, 0x02, 0x3F,

0x7F, 0xF8, 0x00, 0x3F,

0xFF, 0xFC, 0x00, 0x7F,

0xFF, 0xFC, 0x00, 0x7F,

0x7F, 0xF8, 0x0F, 0xFF,

0x3F, 0xC0, 0x3F, 0xFF,

0x00, 0x00, 0x7F, 0xFF,

0x00, 0x00, 0x7F, 0xFF,

0x00, 0x40, 0xFF, 0xFF,

0x00, 0x21, 0xFF, 0xFF,

0x00, 0x71, 0xFF, 0xFF,

0x00, 0x21, 0xFF, 0xFF,

0x20, 0x01, 0xFF, 0xFF,

0x00, 0x01, 0xFF, 0xFF,

0x00, 0x00, 0xFF, 0xFF,

0x00, 0x00, 0x7F, 0xFF,

0x00, 0x00, 0x00, 0xFF,

0x00, 0x78, 0x00, 0x00,

0x01, 0xFC, 0x04, 0x00,

0x0F, 0xFF, 0x00, 0x00,

0x0F, 0xFF, 0x80, 0x08,

0x8F, 0xFF, 0x80, 0x1C,

0x07, 0xFF, 0x00, 0x08,

0x00, 0x00, 0x00, 0x01,

0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x40, 0x00,

0x00, 0x00, 0x00, 0x00,

0x02, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x20

};


void setup() {

Serial.begin(9600);

Wire.begin();


if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

Serial.println(F("SSD1306 allocation failed"));

for (;;);

}


display.clearDisplay();

display.display();

}


void loop() {

// sensor & disp

int rawValue = analogRead(UV_PIN);

float voltage = rawValue * (VREF / 1023.0);

float uvIndex = voltage / 0.1;


if (uvIndex < 0) uvIndex = 0;

if (uvIndex > 11) uvIndex = 11;


bool isHighUV = (uvIndex >= 3.0); //adjust threshold if needed..


display.clearDisplay();


// cloud or sun bitmap

int iconX = 95;

int iconY = 0;


if (isHighUV) {

display.drawBitmap(iconX, iconY, sunBitmap, ICON_WIDTH, ICON_HEIGHT, SSD1306_WHITE);

} else {

display.drawBitmap(iconX, iconY, cloudBitmap, ICON_WIDTH, ICON_HEIGHT, SSD1306_WHITE);

}


// disp uv reading

display.setTextSize(2);

display.setTextColor(SSD1306_WHITE);

display.setCursor(4, 6);

display.print("UV:");

display.setCursor(16, 22);

display.print(uvIndex, 1);


//message

display.setTextSize(1);

display.setCursor(0, 50);

if (isHighUV) {

display.println("Wear your sunscreen!");

} else {

display.println("No sunscreen needed!");

}


display.display();


delay(200);

}

Test

03B19352-3EFA-4152-84D6-D871F8610E7F 2.JPG
IMG_9108.jpg

Try testing it out in the sun or nearby a window to see if the UV changes, and cover the uv photodiode (the small square on the side) to see if it senses uv properly. Now it's done! :))