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
Arduino Uno Setup:
- Reference Voltage: External 3.3V
- UV Sensor Pin: A0
ATTiny85 Setup:
- Reference Voltage: Internal 1.1V
- UV Sensor Pin: Analog pin 3 (corresponds to physical pin 2)
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/cm2
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/cm2
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
-
\$\begingroup\$ Everything is correct, 1.1 V gives an index of around 8.23. Higher sensor voltages leave the configured ADC conversion range of the Tiny85. \$\endgroup\$Jens– Jens2024年07月28日 02:19:41 +00:00Commented Jul 28, 2024 at 2:19
-
\$\begingroup\$ Also note that the datasheet for the Attiny85 gives a range for the internal reference from 1.0 to 1.2V. It's not exactly a precision reference. \$\endgroup\$Mat– Mat2024年07月28日 05:44:36 +00:00Commented Jul 28, 2024 at 5:44
-
\$\begingroup\$ @Jens so what can i do to have a maximum precision? Because two index différence is a lot for me... Change the attiny for other small MCU? thanks for that \$\endgroup\$Naografix– Naografix2024年07月28日 08:38:22 +00:00Commented Jul 28, 2024 at 8:38
-
\$\begingroup\$ Can you add a voltage divider between sensor and ADC, e.g. 20 : 10 kohm? In this case you need a voltage correction factor 3 in the code. \$\endgroup\$Jens– Jens2024年07月28日 13:15:07 +00:00Commented Jul 28, 2024 at 13:15
-
\$\begingroup\$ When you encounter this kind of issue, you should always short-circuit (figuratively speaking) any complex calculations by modifying the code to directly view the raw ADC value from the sensor and compare with the measured voltage at the input pin. \$\endgroup\$Spehro 'speff' Pefhany– Spehro 'speff' Pefhany2024年07月28日 14:54:42 +00:00Commented Jul 28, 2024 at 14:54