Differences in UV Sensor Readings Between Arduino Uno and ATTiny85 Using AnalogReference

Hi everyone,

I've been working on a project involving UV sensor readings using both an Arduino Uno and an ATTiny85. However, I've encountered discrepancies in the UV index values obtained from the two different microcontrollers. Below, I'll explain the setup, the code used, and the differences observed.

Setup Overview

  1. Arduino Uno Setup:

    • Reference Voltage: External 3.3V
    • UV Sensor Pin: A0
  2. ATTiny85 Setup:

    • Reference Voltage: Internal 1.1V
    • UV Sensor Pin: Analog pin 3 (corresponds to physical pin 2)
  3. ADAFRUIT GUVA-S12SD

Issue

Using the same UV sensor, the Arduino Uno provides a UV index of 10.25, while the ATTiny85 gives a reading of 8.25 for the same light conditions. Here are the detailed codes and explanations for both setups.

Arduino Uno Code

#ifdef __AVR_ATtiny85__
  #include <TinyWireM.h>
  #define Wire TinyWireM
#else
  #include <Wire.h>
#endif

#include <Tiny4kOLED.h>   

const int sampleCount = 20;
const int delayTime = 50;
float voltageSum, current, power, sum;

const float referenceVoltage = 3.3; // External reference of 3.3V
const int UVPin = A0; // Analog pin used

void setup() {
  // Serial.begin(9600);
  analogReference(EXTERNAL); // Use external reference of 3.3V
  
  oled.begin();     
  oled.setFont(FONT8X16);    
  oled.clear();
  oled.switchRenderFrame();
  oled.clear();
  oled.switchRenderFrame();
  oled.deactivateScroll();  
  oled.on();  
}

void loop() {
  measureADA();
  delay(1000);
}

void measureADA() { 
  oled.clear();
  voltageSum = 0;
  for (int i = 0; i < sampleCount; i++) {   
    voltageSum += analogRead(UVPin); 
    delay(delayTime);
  }
  voltageSum = (voltageSum / sampleCount) * referenceVoltage / 1023.0;

  float correctedVoltage = voltageSum;
  if (correctedVoltage < 0) correctedVoltage = 0;

  current = correctedVoltage / 4.3; // I in uA
  power = current * 1000.0 / 113.0; // UV power in mW/cm²

  float uvIndex = (current * 1000.0 - 83.0) / 21.0;
  if (uvIndex < 0) uvIndex = 0; 
  
  oled.setCursor(1,1); 
  oled.print(uvIndex); 
}

ATTiny85 Code

#ifdef __AVR_ATtiny85__
  #include <TinyWireM.h>
  #define Wire TinyWireM
#else
  #include <Wire.h>
#endif

#include <Tiny4kOLED.h>   

const int sampleCount = 20;
const int delayTime = 50;
float voltageSum, current, power, sum;

const float referenceVoltage = 1.1; // Internal reference of 1.1V
const int UVPin = 3; // Analog pin used

void setup() {
  // Serial.begin(9600);
  analogReference(INTERNAL); // Use internal reference of 1.1V
  
  oled.begin();     
  oled.setFont(FONT8X16);    
  oled.clear();
  oled.switchRenderFrame();
  oled.clear();
  oled.switchRenderFrame();
  oled.deactivateScroll();  
  oled.on();  
}

void loop() {
  measureADA();
  delay(1000);
}

void measureADA() { 
  oled.clear();
  voltageSum = 0;
  for (int i = 0; i < sampleCount; i++) {   
    voltageSum += analogRead(UVPin); 
    delay(delayTime);
  }
  voltageSum = (voltageSum / sampleCount) * referenceVoltage / 1023.0;

  float correctedVoltage = voltageSum;
  if (correctedVoltage < 0) correctedVoltage = 0;

  current = correctedVoltage / 4.3; // I in uA
  power = current * 1000.0 / 113.0; // UV power in mW/cm²

  float uvIndex = (current * 1000.0 - 83.0) / 21.0;
  if (uvIndex < 0) uvIndex = 0; 
  
  oled.setCursor(1,1); 
  oled.print(uvIndex); 
}

Do you see any mistakes?

Thanks

Have the two microprocessors measure the same accurately known voltage, and see if they report the same value, and whether it is correct. If not, they need to be calibrated.

The voltage references are suspect. The internal 1.1V reference is stable but not calibrated and can be anywhere between 1.0 and 1.2V. Check the 3.3V reference, too.

Didn't read the code. You have two different devices, if they are both 'seeing' the same thing, then adjust one or the other sketches to match the other. What you need is a tie breaker. That is a 3rd instrument that is calibrated and you adjust both sketches to match that.

1 Like

The thing is, I need to measure the sun's uv correctly. For the moment I only have a UV lamp but I don't know how much uv it sends. So I tested with my ATTINY85 but I realized that my Arduino was giving me a different value. So who to listen to, who to trust...
I'll probably do as @jremington said. I'll put 1v as input in my analogread and see how to interpret that.

Even inexpensive multimeters have about 1% accuracy. Your errors are much higher than that, especially the "1.1V" reference. See this ADC tutorial, which covers using and calibrating it.

If you don't have a multimeter, time to get one. They are invaluable for this hobby.

Yes i have multimeter and one power supply. I will test to put 1v and check what i can have!

Thanks for the idea

Then you don't want to rely on this type of sensor which realistically will only ever be able to give a very crude approximation. It lacks any kind of compensation for variations in supply voltage, temperature etc.

1 Like

The UV output from the sun varies tremendously over even short times. Yesterday it output enough UV in a burst to wipe out the radio reflective layers of the ionosphere for several minutes.

Please, perform the following tests for both UNO and ATtiny85 and report the resuults. This is to see that both MCUs are delivering almost identical outputs for the identical inputs (3.3V of UNO's 3.3V-point).

For UNO:

analogReference(DEFAULT);      //5V for Vref-pin of ADC
Serial.println(analogRead(A0));

For ATtiny85:

analogReference(DEFAULT);      //5V for Vref-pin of ADC
oled.print(analogRead(A3));

By the by, how are you programming the ATtiny85 -- using "Arduino as ISP" or "AVR Programmer" or "Digispark Dev Board"?

Perhaps superfluous to remark, but still: your test relies on both Arduinos being connected, with GND's on both devices being shared and the 3V3 from the UNO being fed into the respective analog inputs on each controller.

1 Like

You have pointed the very essential points.

Assuming that OP is using Arduino UNO as "Arduino as ISP" Programmer, then the possible hardware setup could be like Fig-1.

In this setup, UNO will be showing counts for 3.3V at A0-pin on its Serial Monitor at 1-sec interval. The ATtiny85 will be showing counts for 3.3V at A3-pin on its OLED at 1-sec interval. Thre is no reason for both counts NOT to be almost identical.


Figure-1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.