How to Perform UV Monitoring with the Adafruit Si1145

August 03, 2016 by Mark Hughes

Environmental monitoring sensors help us to better measure the world around us. This article will help you understand why the amount of UV light reaching you changes over time and how to measure it over I²C using the Si1145.

This article will help you understand why the amount of harmful Ultraviolet energy changes over time and show you how you can measure it at your location.

Using the Si1145 Board from Adafruit

Humans have photo-receptors in our eyes that detect photons in a very narrow range: between ~400nm and 700 nm (~750-430 THz). When the frequency (energy) of the photons is lower than the range we have evolved to see, the photons are termed infrared. When the frequency is above the range we have evolved to see, the photons have enough energy to burn our skin. These photons are called ultraviolet.



The spectrum of visible light. Image designed by the Florida Center for Environmental Studies.

The Si 1145 is a low power I²C interfaced sensor capable of detecting photons of visible, infrared, and ultraviolet light. The chip and its 8 pins sit within a 2mm x 2mm footprint. This size is too small for hand soldering, so if you're going to play with it, you'll need a breakout-board with an on-board voltage regulator like the Si1145 from Adafruit. Adafruit has also been kind enough to create an Arduino-compatible library which makes it very easy to use the sensor.

Parts Required

Part Price
Si1145 $14
Arduino Uno R3 $17
I2C LCD $13
Male/Female or Male/Male Jumpers $9
Solderless Breadboard $10

You will have to purchase Adafruit's Si1145 and the I²C LCD. If you're a tinkerer, you'll likely have the other parts already on hand.

Here are the datasheets for the LCD (PDF) and the sensor (PDF).

Download Libraries

Next, you'll need to install the appropriate libraries in the Arduino software:  Sketch»Include Library»Manage Libraries

  1. Install LiquidCrystal
  2. Install Adafruit Si1145

I've included .zip files for both libraries below:

Hookup Information

Four wires are required to connect the Arduino to the Si1145. Another four wires to the same four pins are required to connect to the LCD. You might consider using a breadboard to give yourself additional tie points.  On a side note, the signal names used here correspond to the labels on the breakout board.  For the names of the Si1145 pins, please refer to the datasheet.

Follow these steps to get your wiring done:

  1. Gnd on the Arduino to Gnd on the LCD and Si1145
  2. 5V on the Arduino to $$V_{CC}$$ on the LCD and Vin on the Si1145
  3. Analog pin 4 (SDA) on the Arduino to SDA on the LCD and Si1145
  4. Analog pin 5 (SCL) on the Arduino to SCL on the LCD and Si1145


Arduino Si 1145 LCD
5 V $$V_{IN}$$ $$V_{CC}$$
Gnd Gnd Gnd


After you have made the connections, upload and execute the following code:

/* Si1145 UV Sensor I2C Display
 mjhughes for
 Connect the LCD and UV sensor to 5v, Gnd
 Connect LCD & UV SDA to Arduino analog 4
 Connect LCD & UV SCL to Arduino analog 5
 On include lines, use "" for header files in same directory
 or use <> if you installed the libraries

#include                       // I²C library
#include          // control the LCD
#include             // read the UV sensor

Adafruit_SI1145 uv = Adafruit_SI1145();

LiquidCrystal_I2C lcd(0x27,20,4);       // (LCD address, 20 chars wide, 4 characters tall)

void setup()                            // initialization code
  lcd.init();                           // initialize the lcd 
  lcd.backlight();                      // turn backlight on
  uv.begin();                           // initializes the sensor

void loop()                             // main program loop
  float UVindex = uv.readUV();           // variable for UV Index

  UVindex /= 100.0;  // to convert to integer index, divide by 100

  lcd.setCursor(8,0); lcd.print("  ");   // Clear extra digits that can accumulate with high readings
  lcd.setCursor(17,0); lcd.print("  ");  // Clear extra digits that can accumulate with high readings
  lcd.setCursor(19,1); lcd.print(" ");   // Clear extra digits that can accumulate with high readings
  lcd.setCursor(2,0); lcd.print("Vis:"); lcd.print(uv.readVisible()); // Show visible light reading
  lcd.setCursor(11, 0); lcd.print("IR:"); lcd.print(uv.readIR());     // Show infrared light reading
  lcd.setCursor(0,1);  lcd.print("UV Index: "); lcd.print(" "); lcd.print(round(UVindex)); // UV index
  lcd.print(" (");  lcd.print(UVindex); lcd.print(")"); // provides more detailed UV Index

  lcd.setCursor(0,2); lcd.print("                    ");
  lcd.setCursor(0,3); lcd.print(" 1 2 3 4 5 6 7 8 9 +");
  lcd.setCursor(UVindex*2,2); lcd.print("Θ"); // Should move to 2nd line for 11, 12, 13, etc...
  delay(1000);                           // Set an appropriate refresh rate for the application

On your LCD, you should see readings for visible and infrared light, as well as a calculated UV Index and a visual index of readings 1-9+.

When the readings go beyond 9, the cursor should move down to the next line indicating measurements from 10 to 19.


Image photo-manipulated to better show screen.


Here's a video of my LCD in action:

Next Steps

  1. Take your sensor, Arduino, and LCD outside in the middle of the day and see how your readings compare with the weather forecast.
  2. If you have an RGB display, it would be nice to see the graphical UV images from the WHO appear instead of just the numbers (perhaps alongside recommendations for a user to apply sunscreen).
  3. Skin type influences the length of time before a person experiences sunburn. Perhaps create an equation or lookup table that provides a user with a time-to-burn countdown timer.

  4. Find a location where you can break the current UV Index record of 43.3.

More Information About Why the UV Index Changes

The weather forecast gives a UV Index for your forecast region, usually during the local solar noon. However, the amount of UV radiation that reaches the Earth's surface is dynamic. If you need up-to-date information, you have to measure it at the location.



UV forecast map for the United States on July 10th, 2016 from Wolfram Alpha


Daily UV Index

Timelapse hourly UV forecast map for the United States on July 10th, 2016 from Wolfram Alpha

Daily UV Index

The National Weather Service measures the atmospheric Ozone, the cloud-cover, the angle of the sunlight, and a few other variables. Rather than bombard the public with a great many numbers and data points that they may or may not understand, information is aggregated, a UV Index is calculated, and a number is presented to the public.

They also provide a tool to give you a UV Index forecast for a given location.


The EPA UV Index tool. It's interactive! Give it a try.


A number less than 3 on this Index indicates that a moderate amount of sun exposure is okay. Any number greater than 3 and the World Health Organization recommends applying sunscreen and wearing a hat, sunglasses, and pants.


Graphic of the UV index. Image courtesy of the World Health Organization.


The amount of the Sun's energy that makes it to the surface of the earth to give you a sunburn depends on two primary factors—the angle of cast shadows and the atmospheric molecules that get in the way. 

Understanding why the amount of ultraviolet radiation changes over the course of the day, over the course of the year, and with the weather requires a bit more physics. If you're interested, please read on.

A Quantum Theory of Electromagnetic Radiation and Atmospheric Absorption

When electrons moving around the nuclei of atoms transition from higher-energy orbitals to lower-energy orbitals, they emit a photon—electromagnetic energy of specific frequency. That photon travels through space until it is absorbed by another atom and causes an electron to move from a lower-energy orbital to a higher-energy orbital or leave the atom/molecule altogether.  

If the travelling photon's energy doesn't exactly match a transition energy for the atom/molecule, the photon will not be absorbed by the atom. These orbital transitions are nature's tuning forks—they only occur at very specific frequencies (although each frequency can be Doppler-shifted a bit higher or lower through relative motion).


Depiction of electron absorption and emission. Image courtesy of StackExchange.


Every electron orbital has a specific energy associated with it, and the frequency (energy) of the photons that are emitted or absorbed must exactly equal the difference in orbital energies.


Transitions of the Bohr model of atomic Hydrogen. Image designed by WikiMedia.


As atoms gain electrons, the orbitals gain complexity and the frequencies of photons that are produced become more varied. And with complexity comes uniqueness: Each element of the periodic table has a unique fingerprint (or barcode) we can use to identify it. This is the same science that lets us know what distant stars and planets are made of.

Atoms can absorb a photon of one frequency (energy) and emit photons of a different frequency that correspond to different orbital transitions. Atoms can absorb higher-energy photons and emit lower-energy photons, as illustrated below where Uranium Oxide infused in glass is used to convert ultraviolet light to bright green.


Compare the color of the spectral lines around 550 THz of the oxidative state of uranium above to the color of the glass below. Image courtesy of Wolfram Alpha.


Uranium infused glass (Vaseline Glass)

Shining ultraviolet LEDs on Uranium-infused glass causes it to glow neon green. Photo by Mark Hughes.


Our atmosphere is full of atoms and molecules that can absorb photons at one frequency (high-energy) and then re-emit the energy as a series of photons at another frequency (lower-energy). The more atmospheric molecules the ultraviolet photons pass through, the better the chance they will be absorbed and reemitted at lower-frequency, thereby changing much of the harmful ultraviolet radiation to visible or infrared radiation.


Atmospheric Windows

Graphic of how far portions of the EM spectrum can make it through the Earth's atmosphere. Image courtesy of NASA.

Understanding the Angle of Incident Light

The angle of incidence for light changes with the seasons and throughout the daylight hours. It is measured from an imaginary line that is perpendicular to a point on the surface of the Earth to a line that points towards the sun. When the shadows are longest, the intensity of the sunlight is at its lowest as light from the sun spreads out to cover large areas. When shadows are shortest, the intensity of the sunlight is greatest and you are at greatest risk of a sunburn.


As the angle of incidence deviates from the normal, the intensity decreases.

Animation made with Wolfram's Mathematica based on this graphic.

Insolation & the UV Index

These two ideas—the angle of incoming light and the amount of atmospheric absorption—combine to determine the amount of INcoming SOLar radiATION that reaches the earth's surface. We accordingly call this insolation (and from the Latin word insolare).

Since the frequency of radiation affects how harmful it is for our skin, the National Weather Service creates a weighted average over a series of frequencies. It combines the weighted average with the altitude and weather at a given location to determine the UV Index for a location.

For more information on how the UV Index is calculated, visit the EPA webpage or jump straight to their Guide to the UV Index.

To learn more about the International Agency for Research on Cancer, which discusses how UV radiation can lead to cancer, read this article (PDF).

Lastly, if you'd like to use Wolfram's Mathematica (available free on the Raspbian operating system) to create your own graphics, I've included the code I used to create the animations below:

Give this project a try for yourself! Get the BOM.

  • S
    srh76 April 05, 2017

    I have just completed this project with my son. I’d come across this post on facebook and I ordered the parts and couldn’t wait to tackle it. When compiling the code though, it came up with an error regarding the lcd.init(); part of the code. After reading a couple of forums online, I was able to rectify this error by changing the lcd.init(); to lcd.begin();

    Like. Reply
    • Mark Hughes April 05, 2017
      Hi @srh76, Thanks for joining the site! I'm very happy that you were able to solve the problem, and that you like the project. Sorry about the code compilation error -- it's due to the fact that lcd.init() is now deprecated. You are using a newer LiquidCrystal_I2C.h library than I used when I wrote the article. If you're up for it, take a photo of your project with your son and send it to us on facebook or twitter, I'd love to see it. Mark
      Like. Reply
  • S
    Stephen Young June 07, 2019

    Wow!  Great articles, massive amount of references, thanks!

    Like. Reply