UV sensors, Random readings. I am new and lost

I am trying to help my son make a UV meter to test sunscreens for his school project.
We have already gone through a few coding issues, but keep having trouble with he sensors giving us weird random results. I am running them separately on an Arduino Uno R3.
I looked for basic code to run trials with both of them and I was from the get go getting random changes on the readings, going up and down into negative numbers with no apparent reason. I tried taking them outside without much improvement, but I chalked all this to testing them on a cloudy day or with my cell phone light. I purchased a lizard lamp with a bulb that emits both UVA and UVB, When i tested them again they continued giving me random readings that changed every reading without reason, also no noticeable change with distance of the UV source. I have been testing this indoors, in a normal house, in a room with a computer or 2, wifi and no weird electromagnetic interference or chemical weirdness. I have tried changing the delay from .3 seconds to 10 seconds and most everything in between without any noticeable improvement. I tried them with both 3.3 and 5 v without change, I also verified with a multimeter that they were receiving just below the voltage that they were hooked to ( 4.78 to 4.91 when hooked to 5V).
I will copy below the code I used to test them (i got them from the internet One is from Electropeak and the other I am not sure where i got it from) and a picture of the bulb info.
If someone can point me to what i am doing wrong I will appreciate it, since i am at a loss. I have ordered a few more sensors to test, but I feel its weird I have similar bad luck with both sensors.

UVM -30A

   /*
  UVM30A-UV-Module
  Made on 02 Feb 2020
  by Amir Mohammad Shojaee @ Electropeak
  Home

*/
void setup(){ 
  Serial.begin(9600);
}

void loop()
{  
  int sensorValue;

 sensorValue=analogRead(A0);
 Serial.print("The voltage value:");
 Serial.print(sensorValue*5000/1023.0);
 Serial.println("mV");
 delay(1000);
 Serial.print("\n");
}

GUVA-S12SD

void setup() 
{
  Serial.begin(9600);
}
 
void loop() 
{
  float sensorVoltage; 
  float sensorValue;
 
  sensorValue = analogRead(A0);
  sensorVoltage = sensorValue;
  Serial.print("sensor reading = ");
  Serial.print(sensorValue/1024*3.3);
  Serial.println("");
  Serial.print("sensor voltage = ");
  Serial.print(sensorVoltage);
  Serial.println(" V");
  delay(3000);
}


No wiring diagram or schematic?

1 Like

Please post a schematic as requested by aarg, possibly a picture and links to technical information on the hardware devices.

Random readings are a sign of a wiring problem and floating input.

Please post links to the exact UV sensors you have.

This one from Adafruit works as advertised and would be useful for the project:

But, there are clones that have a completely different circuit, and do not.

1 Like

@redkaili please just print the value from analogRead().

void loop() 
{
  Serial.println( analogRead(A0));
  delay(1000);
}

Your calculation is wrong, that's why you get negative numbers.

Do you measure the ambient light, or do you put the sensor in direct sunlight ?

UVM30A sensor

The sensor at ElectroPeak: https://electropeak.com/uvm-30a-uv-light-sensor
Elecrow sells the same module: https://www.elecrow.com/uv-sensor-moduleuvm30a-p-716.html.
This seems a nice tutorial (with Chinese datasheet): https://www.mysensors.org/build/uv
The sensor gives a value for the UV index.
Maximum 85 °C working temperature.

GUVA-S12SD

This sensor at ElectroPeak: https://electropeak.com/analog-uv-light-sensor-guva-s12sd
This sensor at Adafruit: https://www.adafruit.com/product/1918
Adafruit pcb files: https://github.com/adafruit/Adafruit-GUVA-Analog-UV-Sensor-Breakout-PCB

Adafruit schematic:
afbeelding
The circuit is sensitive for noise. I trust the Adafruit module that it works okay. I don't know about the ElectroPeak module.

[ADDED]
Here is a example that shows good and bad math:

void setup()
{ 
  Serial.begin(9600);
}

void loop()
{  
  int sensorValue;

  sensorValue = random(0,1024);     // analogRead(A0);  // 0...1023

  Serial.print( "Bad value: ");
  auto n = Serial.print( sensorValue * 5000 / 1023.0);  // <-- Bad
  Serial.print( " mV.");

  for( int i=n; i<8; i++)
    Serial.print( " ");
  Serial.print( "Good value: ");
  float voltage = float( sensorValue) * 5.0 / 1024.0;   // <-- Good
  Serial.print( voltage);
  Serial.println( " V.");

  delay(1000);
}

This sketch in Wokwi:

For everyone else: I know there is also a good and bad voltage reference, this sketch is only about the math.

Your issues are multiple.

void loop() 
{
  float sensorVoltage; 
  float sensorValue;
 
  sensorValue = analogRead(A0);
  sensorVoltage = sensorValue;

Your most critical issue is design. The sample code is simply to prove the sensor responds to light: most common light sources have UV components.
To properly use these "type" of analog sensors, AC shielding is mandatory: shielded box, proper wiring, RF bypass caps on all external connections entering the enclosure.
Another "concern" is that the Arduino is fast enough to register any power fluctuations in the fluorescent UV lamp. UV LEDs provide a stable light source. Even with a stable intensity, averaging multiple analog readings is a best practice.

Wow, thank you guys, I am sorry, still learning but will be better next time.

First Schematics, here is what I was able to make in Tinkercad, I couldn't find a UV sensor so this is what looked the most similar

And this is a picture

the sensor pictured is a SMAKN UVM-30A purchased from amazon, I could not find a schematic of how this sensor is made. I apologize, but maybe I just don't know yet where to look for it.

This is the info I could find about it:
Product Name : UV Sensor Module;Model : UVM-30A;Operating Voltage : DC3-5V
Output Voltage : DC0-1V;Operating Current : 0.06mA(Typical),0.1mA(Max.);Response Wavelength : 200nm-370nm
Operating Temperature : -20C to -85C ;Testing Accuracy : +/- 1UV Index;Total Size : 35 x 13 x 7mm/1.4" x 0.51" x 0.28"(LWT)
Material : Plastic, PCB, Iron;Color : Black
Weight : 3g;Package : 1 x UV Sensor Module

Product Name : UV Sensor Module;
Model : UVM-30A;Operating Voltage : DC3-5V
Output Voltage : DC0-1V;
Operating Current : 0.06mA(Typical),0.1mA(Max.);
Response Wavelength : 200nm-370nm
Operating Temperature : -20C to -85C ;
Testing Accuracy : +/- 1UV Index;
Total Size : 35 x 13 x 7mm/1.4" x 0.51" x 0.28"(LWT)
Material : Plastic, PCB, Iron;
Color : Black
Weight : 3g;Package : 1 x UV Sensor Module

The other Sensor i used was the Adafruit GUVA-S12SD, also purchased from Amazon and pictured above by Koepel.

I used Koepel's code with the SMAKN UVM-30A and definitely got much more consistent readings, I learned the lamp needs time to warm up and changed the delay a few times, It seems like 2 seconds is the most consistent but I want to tinker more with it.

I have ordered a better lamp from a company called ExoTerra, its UV radiation profile mimics sunlight better, It is discontinued but we were able to get one by calling the company directly, hopefully it arrives in the next few days.

I am mostly testing at night indoors, with ambient light the sensors don't read anything, only when exposed to my cell light and now with the UV bulb, but they have to be fairly close.

Because the bulbs generate some heat, I was planning to make our rig inside an old PC case, with the light up top and the fans running. (if we have some time we will try to put temp/humidity sensors inside the box). But from what i can see now, in order to generate larger readings with a lower variability, I think we will need to have the light source right on top of the sample plates which must be just a couple mm above the sensor if we want to see any difference between sunscreen samples.
We are trying to set up our experiment as close as we can to what the FDA requires for their in vitro test without breaking the bank.

https://www.accessdata.fda.gov/scripts/cdrh/cfdocs/cfcfr/cfrsearch.cfm?fr=201.327

So if we can get the UV meter right and a better UV source, we plan to apply sunscreen to sandblasted PMMA plates that we already have, let it dry 10 min, then pre expose the plate to UV rays for 15 min and then do the measurements with a thin layer of teflon film in between as a diffuser to avoid collimated radiation (I am yet to test if the film we got works for this purpose. The FDA calls for 5 different areas of the plate on 3 different plates per product. We cannot do that and we are thinking about getting readings from 3 different spots on a single plate per product. Each measurement being the average of I am not sure how many measurements within 5-30 seconds. The control plate will be covered with glycerin.

The ultimate goal is to obtain transmittance readings (maybe convert them to absorbance if it looks better for his report) that my son can use to compare the different sunscreen samples we have to test.

I will now put my head down to try to understand the code examples posted above by Koepel and read on proper shielding as MrBurnette suggested.
The glaring issues with my design, as you all can see, are the result of my total ignorance, I just thought I made a big discovery when the IDE finally compiled a bunch of gibberish I just mashed together without knowing what any of it means. But with your help I am starting to learn ( mostly that this is the realm of smart people and I am way out of my leage)
Thank you all very much for all your help. The curve is still pretty steep for me, but your input helps me a lot.

Here is a quick update, I have a few more questions but I will try to ask them one by one.

I now have a schematic and a working sketch (I learned to use Fritzing. Code: not yet).


/*
   Based on the work of the following sources:
   
Intervals
  Print serial text with different intervals.   
  Check the array with a for-loop.
  created 01-12-2009 by kasperkamperman.com

Smoothing
  Reads repeatedly from an analog input, calculating a running average and
  printing it to the computer. Keeps ten readings in an array and continually
  averages them.
  The circuit:
  - analog sensor (potentiometer will do) attached to analog input 0
  created 22 Apr 2007
  by David A. Mellis  <dam@mellis.org>
  modified 9 Apr 2012
  by Tom Igoe

Temp Sensor 
  TMP36-Temperature -Sensor
  made on 07 Nov 2020
  by Amir Mohammad Shojaee @ Electropeak
  Home 

  
  Modified by MN & KN


*/


#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display



const int amountOfIntervals = 3;

unsigned long previousMillis[amountOfIntervals]  = {0, 0, 0};
unsigned long currentMillis                      = 0;

int intervals[amountOfIntervals]       = {100, 5000, 200};

const int numReadings1 = 10;

int readings1[numReadings1];      // the readings from the analog input
int readIndex1 = 0;              // the index of the current reading
int total1 = 0;                  // the running total
int average1 = 0;                // the average

int inputPin1 = A0;



const int numReadings2 = 10;

int readings2[numReadings2];      // the readings from the analog input
int readIndex2 = 0;              // the index of the current reading
int total2 = 0;                  // the running total
int average2 = 0;                // the average

int inputPin2 = A1;

 int x;
float tem = 0;


void setup() {
 
    lcd.init();
  
  
  // opens serial port, sets data rate to 57600 bits per second
  Serial.begin(57600);   
}

void loop()



{ // save number of milliseconds since the program started
  currentMillis = millis();
  
  // check the 3 intervals one by one with a for-loop. 
  for(int i=0; i<amountOfIntervals; i++) { 
    
    // check to see if the interval time is passed. 
    if (currentMillis - previousMillis[i] >= intervals[i]) {  

      
      if(i==0) Serial.println(average1);
      if(i==1) Serial.println(tem);
      // if(i==2) Serial.println("text text");





lcd.backlight();
  lcd.setCursor(2,0);
  lcd.print("MarcoMeter W1000");
  lcd.setCursor(1,3);
  lcd.print ("UV SensorVal:");
  lcd.setCursor(16,3);
  if(i==0) lcd.print(average1);
  lcd.setCursor(11,1);
  lcd.print ("T:");
  lcd.setCursor(13,1);
  if(i==1) lcd.print(tem);
  lcd.setCursor(18,1);
  lcd.print ((char)223);
  lcd.setCursor(19,1);
  lcd.print ("F");






      
      
      // save the time when we displayed the string for the last time
      previousMillis[i] = currentMillis; 


// subtract the last reading:
  total1 = total1 - readings1[readIndex1];
  // read from the sensor:
  readings1[readIndex1] = analogRead(inputPin1);
  // add the reading to the total:
  total1 = total1 + readings1[readIndex1];
  // advance to the next position in the array:
  readIndex1 = readIndex1 + 1;

  // if we're at the end of the array...
  if (readIndex1 >= numReadings1) {
    // ...wrap around to the beginning:
    readIndex1 = 0;

  }

  // calculate the average:
  average1 = total1 / numReadings1;


// subtract the last reading:
  total2 = total2 - readings2[readIndex2];
  // read from the sensor:
  readings2[readIndex2] = analogRead(inputPin2);
  // add the reading to the total:
  total2 = total2 + readings2[readIndex2];
  // advance to the next position in the array:
  readIndex2 = readIndex2 + 1;

  // if we're at the end of the array...
  if (readIndex2 >= numReadings2) {
    // ...wrap around to the beginning:
    readIndex2 = 0;




 x=analogRead(inputPin2);//read sensor pin
  
  float voltage=x*5.0;
  voltage /=1024.0;
tem=((voltage-0.5)*100.0*1.8)+32; //convert voltage data to temperature

       
    }
  }
  } }

I wanted to ask if someone can help me solve the quandary i am on with the sensors.
I have gotten a few different ones as I am kind of desperate:

Early on I got an Adafruit GUVA-S12LD and a UVM 30A from Amazon.
Links are above in the thread along with a schematic of the Adafruit GUVA sensor.

Unfortunately I think I somehow killed the Adafruit and The UVM kept giving me inconsistent and fluctuating readings.

I since have purchased a couple of Waveshare GUVA S12SD sensors

Also a CMJMCU GUVA S12SD that I do not remember where I got from and can't find record in my CC or email. But it can be seen here:

Both of these are promising, despite having the same technology, their sensitivity varies a lot. They both take 20 or 30 seconds to stabilized once exposed to the UV lamp but after that they are steady (I have tested them both for 6-8 min continuously)
We are still using a fluorescent lizard bulb, we purchased metal halide bulb with better UV spectrum but it arrived broken and a replacement may not get here in time.

The Waveshare (blue) gives very consistent readings although much lower, in the range of 300 to 600 with the bulb 1 cm away.
The CMJMCU (purple) is much more sensitive, which we liked because it makes our lives easier to see small variations once we start comparing sunscreen samples. The problem is that the reading tops out at 1021 or 1019 even with the lamp 6 inches away. which is a problem to us since our sample sits very close to it in our device. I tried using a simple sketch to test it and that did not correct the problem.

For the time being it seems like we are going to have to settle for the Waveshare.

My question is the following:

Is there a way to calibrate the CMJCU sensor to give us the higher readings it is missing?

Thank you

There are at least two different designs for those UV sensor modules, with amplifier gains that are vastly different. The higher gain version is just about useless to measure sunlight and similar intense UV sources.

The Adafruit sensor and close copies work fine, if you use an ADC with ~ 1 V full scale (such as an Arduino Uno, using the 1.1V internal ADC reference).

To calibrate you will need an instrument that is already calibrated so you can compare the readings and create a formulae or a look up table for the correction value.

It's perhaps an op-amp and linear circuit question?
The datasheet for the GUVAS12SD is here:
http://www.geni-uv.com/download/products/GUVA-S12SD.pdf
That gives you the current generated vs W/m2 of UV light.
From that and the op-amp schematic you should be able to work out out voltage vs uv intensity.
By changing a resistor or 2, you could change the op amp's working range to a different range of uv light levels?
The datasheet suggests that diode is good for up to 100mw per sqcm of UV, not sure how that relates to summer sunlight? The graphs on the data sheet show its operating range goes up to at least 3x the UV irradiance of when the UV index is 15, so if you're working above that range I'd be more concerned about fried retinas than your code/circuit not working?

Thank you for the input, I will stick with the Waveshare sensor. But this afternoon I will try messing around with the CMJCU with a couple resistors. I won't know what i will be doing, but I may learn a thing or 2.
Digging a bit around last night I came across a couple sites offering clones of the VEML6075 from Vishay with dual readings of UVB and UVA that would have been perfect for this project. I gave up on it early on when I saw it on backorder from Sparkfun and discontinued in Adafruit. Unfortunately these places are in Europe and China and it will not arrive on time.

Thank you again.

Hello guys, I just wanted to ask if someone can take a look at my code. I changed my temp sensor from a TMP36 to an AHT20, it seems better and also gives me humidity, but somehow implementing it with the intervals code I was using made my UV readings sluggish. I am using the smoothing code example and my results were tighter but they changed fast, sometimes faster than the LCD could handle. After the AHT20, that changed and the UV updates in the LCD were every few seconds.
I thought it had to do with the intervals code somehow, so I set out to fix it the only way I know, that is, find some other thing that looks like it may work. I came across with this page and basically substituted old lines for new ones.

All I want is smooth UV readings that are as steady as possible so i can trust them and just reassurance that temp and humidity are ok( every 5 seconds is more than fine.

I have modified the millis for the UV read from 100 to 10 to 5 ms, also changed the smoothing number of events from 10 to 100 and I don't see much difference, (variability of readings is still around 1.5 to 2%). I have noticed that while I think I am asking both the serial monitor and the LCD to read the same number, the LCD changes every 3-4 seconds, while the serial prints sometimes twice or even three times with the same time stamp

04:10:33.604 -> UV: 652.54
04:10:33.638 -> UV: 649.27
04:10:33.672 -> UV: 652.54
04:10:33.672 -> UV: 653.27
04:10:33.705 -> UV: 652.05
04:10:33.739 -> UV: 653.42
04:10:33.772 -> UV: 649.32
04:10:33.772 -> UV: 651.27
04:10:33.805 -> UV: 650.49
04:10:33.838 -> UV: 652.00
04:10:33.838 -> UV: 654.35
04:10:33.872 -> UV: 651.66
04:10:33.907 -> UV: 652.49
04:10:33.907 -> UV: 652.54
04:10:33.941 -> UV: 652.15
04:10:33.974 -> UV: 651.37
04:10:33.974 -> UV: 651.56
04:10:34.008 -> UV: 652.00
04:10:34.043 -> UV: 650.78
04:10:34.043 -> UV: 654.39
04:10:34.077 -> UV: 650.68
04:10:34.111 -> UV: 649.95
04:10:34.147 -> UV: 651.95
04:10:34.147 -> UV: 651.95
04:10:34.181 -> UV: 653.03
04:10:34.181 -> UV: 651.66
04:10:34.214 -> UV: 652.05
04:10:34.248 -> UV: 652.25
04:10:34.281 -> UV: 652.44
04:10:34.281 -> UV: 649.71
04:10:34.316 -> UV: 649.71
04:10:34.350 -> UV: 651.03
04:10:34.350 -> UV: 653.12
04:10:34.385 -> UV: 653.03
04:10:34.421 -> UV: 650.63
04:10:34.421 -> UV: 651.66
04:10:34.455 -> UV: 652.15
04:10:34.489 -> UV: 654.20
04:10:34.489 -> UV: 652.00
04:10:34.527 -> UV: 649.71
04:10:34.561 -> UV: 651.17
04:10:34.561 -> UV: 651.46
04:10:34.595 -> UV: 653.81
04:10:34.628 -> UV: 652.49
04:10:34.628 -> UV: 652.15
04:10:34.666 -> UV: 649.32
04:10:34.703 -> UV: 650.68
04:10:34.703 -> UV: 652.10
04:10:34.736 -> UV: 652.88
04:10:34.771 -> UV: 652.78
04:10:34.771 -> UV: 650.44
04:10:34.804 -> UV: 654.15
04:10:34.838 -> UV: 651.95
04:10:34.941 -> Temp: 26.93
04:10:34.941 -> H: 52.80
04:10:35.010 -> UV: 656.45
04:10:35.047 -> UV: 658.94
04:10:35.047 -> UV: 654.20
04:10:35.082 -> UV: 657.81
04:10:35.115 -> UV: 654.64
04:10:35.149 -> UV: 660.16
04:10:35.149 -> UV: 658.54
04:10:35.182 -> UV: 658.45
04:10:35.216 -> UV: 660.84
04:10:35.216 -> UV: 661.82
04:10:35.253 -> UV: 656.54
04:10:35.286 -> UV: 659.72
04:10:35.286 -> UV: 659.62
04:10:35.322 -> UV: 656.59
04:10:35.360 -> UV: 658.94
04:10:35.360 -> UV: 656.49
04:10:35.393 -> UV: 657.23
04:10:35.431 -> UV: 657.96
04:10:35.431 -> UV: 657.52
04:10:35.464 -> UV: 657.23
04:10:35.498 -> UV: 658.40
04:10:35.498 -> UV: 654.74
04:10:35.531 -> UV: 656.64
04:10:35.564 -> UV: 656.49
04:10:35.564 -> UV: 659.52
04:10:35.598 -> UV: 657.62
04:10:35.631 -> UV: 659.81
04:10:35.631 -> UV: 653.32
04:10:35.669 -> UV: 656.01
04:10:35.704 -> UV: 658.98
04:10:35.704 -> UV: 658.45
04:10:35.738 -> UV: 657.18
04:10:35.772 -> UV: 661.43
04:10:35.772 -> UV: 657.76
04:10:35.807 -> UV: 656.35
04:10:35.840 -> UV: 654.39
04:10:35.840 -> UV: 657.91
04:10:35.873 -> UV: 659.33
04:10:35.907 -> UV: 657.28
04:10:35.907 -> UV: 657.91
04:10:35.941 -> UV: 658.20
04:10:35.977 -> UV: 657.96
04:10:36.013 -> UV: 658.59
04:10:36.013 -> UV: 656.93
04:10:36.047 -> UV: 657.71
04:10:36.047 -> UV: 655.81
04:10:36.081 -> UV: 658.20
04:10:36.115 -> UV: 657.67
04:10:36.151 -> UV: 655.57
04:10:36.151 -> UV: 656.10
04:10:36.186 -> UV: 656.59
04:10:36.220 -> UV: 652.44
04:10:36.220 -> UV: 656.79
04:10:36.254 -> UV: 657.76
04:10:36.288 -> UV: 657.76
04:10:36.288 -> UV: 655.91
04:10:36.327 -> UV: 655.62
04:10:36.327 -> UV: 655.52
04:10:36.360 -> UV: 656.30
04:10:36.394 -> UV: 654.15
04:10:36.428 -> UV: 655.47
04:10:36.428 -> UV: 659.57
04:10:36.463 -> UV: 653.96
04:10:36.497 -> UV: 655.71
04:10:36.497 -> UV: 658.94
04:10:36.531 -> UV: 656.74
04:10:36.564 -> UV: 657.81
04:10:36.564 -> UV: 655.81
04:10:36.598 -> UV: 656.45
04:10:36.631 -> UV: 658.06
04:10:36.631 -> UV: 656.20
04:10:36.669 -> UV: 658.84
04:10:36.703 -> UV: 657.47
04:10:36.703 -> UV: 659.03
04:10:36.737 -> UV: 658.01
04:10:36.770 -> UV: 659.03
04:10:36.770 -> UV: 657.08
04:10:36.807 -> UV: 656.30
04:10:36.844 -> UV: 658.69
04:10:36.844 -> UV: 659.28
04:10:36.878 -> UV: 660.21
04:10:36.912 -> UV: 662.84
04:10:36.912 -> UV: 657.91
04:10:36.946 -> UV: 655.76
04:10:36.979 -> UV: 654.00
04:10:37.014 -> UV: 655.62
04:10:37.014 -> UV: 658.15
04:10:37.048 -> UV: 656.88
04:10:37.085 -> UV: 657.81
04:10:37.085 -> UV: 658.69
04:10:37.121 -> UV: 655.37
04:10:37.121 -> UV: 656.74
04:10:37.155 -> UV: 657.18
04:10:37.189 -> UV: 656.20
04:10:37.222 -> UV: 658.25
04:10:37.222 -> UV: 655.13
04:10:37.256 -> UV: 658.59
04:10:37.290 -> UV: 658.50
04:10:37.290 -> UV: 657.13
04:10:37.324 -> UV: 657.62
04:10:37.360 -> UV: 656.74
04:10:37.360 -> UV: 654.74
04:10:37.393 -> UV: 655.62
04:10:37.427 -> UV: 655.91
04:10:37.427 -> UV: 658.79
04:10:37.461 -> UV: 660.94
04:10:37.497 -> UV: 658.84
04:10:37.497 -> UV: 658.20
04:10:37.530 -> UV: 657.47
04:10:37.564 -> UV: 657.91
04:10:37.564 -> UV: 657.67
04:10:37.598 -> UV: 660.89
04:10:37.632 -> UV: 658.35
04:10:37.632 -> UV: 659.81
04:10:37.668 -> UV: 655.03
04:10:37.704 -> UV: 657.91
04:10:37.704 -> UV: 658.74
04:10:37.738 -> UV: 656.88
04:10:37.772 -> UV: 657.37
04:10:37.772 -> UV: 656.69
04:10:37.806 -> UV: 656.88
04:10:37.839 -> UV: 655.27
04:10:37.877 -> UV: 656.79
04:10:37.877 -> UV: 660.25
04:10:37.910 -> UV: 657.71
04:10:37.910 -> UV: 658.50
04:10:37.945 -> UV: 659.03
04:10:37.978 -> UV: 659.52
04:10:38.013 -> UV: 658.06
04:10:38.013 -> UV: 657.81
04:10:38.048 -> UV: 659.52
04:10:38.081 -> UV: 659.72
04:10:38.081 -> UV: 657.81
04:10:38.115 -> UV: 657.13
04:10:38.148 -> UV: 661.57
04:10:38.148 -> UV: 663.57
04:10:38.183 -> UV: 662.21
04:10:38.217 -> UV: 657.86
04:10:38.217 -> UV: 659.86
04:10:38.250 -> UV: 658.64
04:10:38.287 -> UV: 660.89
04:10:38.287 -> UV: 655.96
04:10:38.321 -> UV: 656.59
04:10:38.356 -> UV: 660.99
04:10:38.356 -> UV: 659.91
04:10:38.389 -> UV: 660.60
04:10:38.427 -> UV: 659.03
04:10:38.427 -> UV: 658.06
04:10:38.462 -> UV: 659.72
04:10:38.498 -> UV: 659.37
04:10:38.498 -> UV: 659.67
04:10:38.532 -> UV: 661.87
04:10:38.566 -> UV: 657.42
04:10:38.566 -> UV: 659.18
04:10:38.604 -> UV: 658.54
04:10:38.639 -> UV: 658.40
04:10:38.639 -> UV: 659.67
04:10:38.677 -> UV: 659.03
04:10:38.710 -> UV: 656.49
04:10:38.710 -> UV: 660.06
04:10:38.744 -> UV: 658.30
04:10:38.778 -> UV: 657.62
04:10:38.778 -> UV: 659.72
04:10:38.811 -> UV: 658.06
04:10:38.846 -> UV: 659.08
04:10:38.846 -> UV: 656.84
04:10:38.880 -> UV: 658.45
04:10:38.913 -> UV: 660.06
04:10:38.913 -> UV: 659.28
04:10:38.947 -> UV: 658.54
04:10:38.980 -> UV: 658.79
04:10:39.014 -> UV: 659.52
04:10:39.014 -> UV: 657.42
04:10:39.047 -> UV: 657.28
04:10:39.081 -> UV: 656.98
04:10:39.081 -> UV: 657.32
04:10:39.115 -> UV: 659.23
04:10:39.149 -> UV: 655.42
04:10:39.149 -> UV: 657.71
04:10:39.183 -> UV: 659.52
04:10:39.217 -> UV: 659.28
04:10:39.217 -> UV: 658.84
04:10:39.250 -> UV: 658.11
04:10:39.288 -> UV: 657.62
04:10:39.288 -> UV: 660.35
04:10:39.321 -> UV: 659.47
04:10:39.355 -> UV: 657.86
04:10:39.355 -> UV: 660.55
04:10:39.388 -> UV: 659.23
04:10:39.424 -> UV: 659.37
04:10:39.461 -> UV: 658.15
04:10:39.461 -> UV: 657.23
04:10:39.497 -> UV: 656.79
04:10:39.497 -> UV: 658.84
04:10:39.530 -> UV: 659.57
04:10:39.566 -> UV: 660.01
04:10:39.566 -> UV: 660.25
04:10:39.601 -> UV: 655.96
04:10:39.638 -> UV: 659.57
04:10:39.638 -> UV: 658.89
04:10:39.672 -> UV: 658.15
04:10:39.706 -> UV: 658.98
04:10:39.706 -> UV: 657.32
04:10:39.740 -> UV: 658.89
04:10:39.777 -> UV: 660.25
04:10:39.777 -> UV: 659.33
04:10:39.811 -> UV: 658.89
04:10:39.844 -> UV: 660.06
04:10:39.950 -> Temp: 26.91
04:10:39.950 -> H: 52.78
04:10:40.021 -> UV: 659.96
04:10:40.055 -> UV: 659.86
04:10:40.090 -> UV: 662.40
04:10:40.090 -> UV: 660.01
04:10:40.124 -> UV: 659.67
04:10:40.157 -> UV: 655.52
04:10:40.157 -> UV: 658.84
04:10:40.191 -> UV: 661.87
04:10:40.229 -> UV: 660.50
04:10:40.229 -> UV: 661.04
04:10:40.264 -> UV: 657.28
04:10:40.297 -> UV: 658.50
04:10:40.297 -> UV: 658.94
04:10:40.332 -> UV: 658.69
04:10:40.365 -> UV: 655.96
04:10:40.365 -> UV: 659.96
04:10:40.399 -> UV: 659.67

Here is the sketch as it looks now:




/*
   Based on work by the following sources:
   
Sensors
  by Michael James (May 2019) 
  https://www.programmingelectronics.com/arduino-millis-multiple-things/?utm_source=YouTube&utm_medium=Video%20Description&utm_campaign=Lead%20Gen&utm_content=millis%206

Smoothing
  created 22 Apr 2007
  by David A. Mellis  <dam@mellis.org>
  modified 9 Apr 2012
  by Tom Igoe
  This example code is in the public domain. 
  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Smoothing
  
AHT20 library
   Priyanka Makin @ SparkFun Electronics
   Original Creation Date: March 31, 2020
   http://librarymanager/All#Qwiic_Humidity_AHT20

LCD info
  https://wiki.dfrobot.com/I2C_TWI_LCD2004_Module__Arduino_Gadgeteer_Compatible___SKU_DFR0154_#target_5

  
  Modified by MN & KN. Jan 15, 2022.


*/



//Libraries
  #include <LiquidCrystal_I2C.h>
  #include <SparkFun_Qwiic_Humidity_AHT20.h>
  #include <Wire.h>


//Declarations
  AHT20 humiditySensor;
  LiquidCrystal_I2C lcd(0x27,20,4); 


//Millis stuff
  const long eventTimeGUVA = 10; //in ms
  const long eventTimeT_H = 5000; //in ms
  unsigned long previousTime_1 = 0;
  unsigned long previousTime_2 = 0;




void setup()


{
  lcd.init();
  Serial.begin(9600);
  Wire.begin(); //Join I2C bus

  
  //Weird stuff that makes LCD to crash and temp read negative if i take it out
  if (humiditySensor.begin() == false)  { 
    Serial.println("AHT20 not detected. Please check wiring. Freezing.");
    while (1); 
    }
  Serial.println("AHT20 acknowledged.");
 }




//Smoothing GUVA12SD setup
const int numReadings = 100;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;               // the index of the current reading
float total = 0;                 // the running total
float average = 0;               // the average
float inputPin = A0;
float UVmVolts = 0;



void loop()

{

 /* Updates frequently */
  unsigned long currentTime = millis();

  /* This is my event_1 */
  if ( currentTime - previousTime_1 >= eventTimeGUVA) {
  
    //Smooth GUVA12SD
  total = total - readings[readIndex];           // subtract the last reading
  readings[readIndex] = analogRead(inputPin);     // read from the sensor
  total = total + readings[readIndex];           // add the reading to the total
  readIndex = readIndex + 1;                      // advance to the next position in the array
  if (readIndex >= numReadings) {                 // if we're at the end of the array... 
  readIndex = 0;                                  // ...wrap around to the beginning
  average = total / numReadings;                // calculate the average
  UVmVolts = average/1.024*5.0;

    
    
    
    Serial.print("UV: ");
    Serial.println(UVmVolts);
    
    /* Update the timing for the next event*/
    previousTime_1 = currentTime;
  }

    /* This is my event_2 */
  if ( currentTime - previousTime_2 >= eventTimeT_H) {
    float temperature = humiditySensor.getTemperature();
    float humidity = humiditySensor.getHumidity();
    Serial.print("           Temp: ");
    Serial.println(temperature);
    Serial.print("           H: ");
    Serial.println(humidity);




    /* Update the timing for the next event*/
    previousTime_2 = currentTime;




    
  //LCD
  lcd.backlight();
  lcd.setCursor(6,3);
  lcd.print(UVmVolts);
  lcd.setCursor(12,1);
  lcd.print(temperature);
  lcd.setCursor(12,2);
  lcd.print(humidity);

  lcd.setCursor(2,0);
  lcd.print("MarcoMeter W1000");
  lcd.setCursor(1,3);
  lcd.print ("UVt:");
  lcd.setCursor(14,3);
  lcd.print ("mV");
  lcd.setCursor(9,1);
  lcd.print ("T:");
  lcd.setCursor(17,1);
  lcd.print ((char)223);  //degree
  lcd.setCursor(18,1);
  lcd.print ("C");
  lcd.setCursor(9,2);
  lcd.print ("H:");
  lcd.setCursor(17,2);
  lcd.print ("%RH");
  }  } 
  
  
  }

Finally before someone rips me another, A while ago Koepel had pointed I wrote poorly the UV readings conversion to mV instead of V (I think its worse now than it was then). I reluctantly chose again to use mV, because it gives me numbers that are easier to use and see in a graph or table for my son's report. I was happy to just go with the raw analog read for this since we would be calculating percentages, but my FIL kept asking what does that number mean and we figured teachers would also ask. I was hoping to convert to µW/cm2, but none of the lamps literature would report irradiance at 1 in (We can't use it farther, because the readings become too low) and after half a day looking into it, we figured calculating it from the irradiance quoted in the box at 4,8,12,16, etc inches would be a nightmare. I switched to an Arduino nano for space savings and I am running t all inside an enclosure with a phone power bank as energy source. The UV lamp is separate and it does need to be hooked up to the wall. Below is a picture and the updated schematic I don't understand much of it, but some of you have asked for it before.

Again, thank you very much in advance.

UV NANO_schem.pdf (652.2 KB)

Hi,
You should be able to export your schematic as a jpg or png, so it will load as an image in the post.
@redkaili circuit.


What are F1 to F3?

Tom.. :grinning: :+1: :coffee: :australia:

OK, next time. Thank you! :upside_down_face:

Hi,
What are F1 to F4?

Tom... :grinning: :+1: :coffee: :australia:

Oh, those are 40 mm fans to help with the heat from the lamp. I'm not sure they do much, but at least they are quiet.