Maker Pro
Maker Pro

running project on lithium battery and reading constant battery voltage adc

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,098
Joined
Nov 17, 2011
Messages
13,098
Your code:
serial.print ("ADC A0 = ");
serial.println(ADC_A0 );
serial.print ("A0Voltage = ");
serial.println(A0Voltage );
doesn't match the output:
A0Voltage = 0.22
ADC A0 = 358
A0Voltage = 0.38
ADC A0 = 391
...
According to the code the output should start with "ADC A0 = ..." but it starts with "A0Voltage = ...". A copy paste error only?
it does not work without this command ADCSRB = (1<<ADLAR);
Wrong. The code in post #8 obviously works without this instruction. And apart from the above mentioned error, and ADC value of 1023 gives a voltage of 1.1 V. Exactly what was expected.
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
Why do you keep messing with the ADC registers? The analogRead() function will do all the necessary settings.
ok i think it will work now the issue was with the code, instead of >= i made <= that's why the code was not working
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
Your code:

doesn't match the output:

According to the code the output should start with "ADC A0 = ..." but it starts with "A0Voltage = ...". A copy paste error only?

Wrong. The code in post #8 obviously works without this instruction. And apart from the above mentioned error, and ADC value of 1023 gives a voltage of 1.1 V. Exactly what was expected.

Ahan, okay, it is not copy paste error. idk what the issue is with this code. currently i am using this working code.

#include <SoftwareSerial.h>
int led = 7;
#define rx 1
#define tx 0
SoftwareSerial serial (rx,tx);
uint8_t adc_lobyte;
uint16_t raw_adc;
void setup() {
pinMode (rx, INPUT);
pinMode (tx, OUTPUT);
serial.begin (9600);
pinMode (led, OUTPUT);
analogReference (INTERNAL);
ADCSRB = (0<<ADLAR);

}

void loop() {
float voltage = (analogRead(2)/1023*(1.1)*(5.7));
adc_lobyte = ADCL;
raw_adc = ADCH<<8 | adc_lobyte; // raw_adc should be declared as uint16_t

serial.print ("solar panel voltage");
delay(1000);

if ( raw_adc>=1023){ // issue was here before i made it <=
digitalWrite (led, HIGH);
}
else{
digitalWrite (led, LOW);
}
}
 
Last edited by a moderator:

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,098
Joined
Nov 17, 2011
Messages
13,098
adc_lobyte = ADCL;
raw_adc = ADCH<<8 | adc_lobyte; // raw_adc should be declared as uint16_t
You can do that, but what's the use of this?
analogRead() does give you excatly this value:
raw_adc = AnalogRead(2)
then you can calculate the voltage from this:
float voltage = raw_adc/1023*(1.1)*(5.7));

Have you ever read the documentation and the examples for analogRead()?


currently i am using this working code.
Why do you declare this code as "working code"?
There is a single print statement:
serial.print ("solar panel voltage");
Which outputs a constant string. There is no way you see the result of the ADC conversion in your output. No wonder it is "working" :(

C:
if ( raw_adc>=1023){ // issue was here before i made it <=
digitalWrite (led, HIGH);
}
else{
digitalWrite (led, LOW);
}
Regardless of ">=" or "<" this statement makes no sense at all. As I tried to explain many times before: the raw ADC value is a number between 0 and 1023. Never higher.
So where your previous statement using <= was always true (LED always on), this statement using ">=" will never be true (LED always off).
Why and under which conditions do you want the LED to be on or off?

When you state that a particular code "doesn't work" you need to supply:
- expected behaviour (how it should work)
- real behaviour (what it does instead)
- relevant input data

Also: have you ever actually measured the voltage at the analog input pin (e.g. with a multimeter) and compared the measuerement with the output of your program? That will be the real world test.
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
You can do that, but what's the use of this?
analogRead() does give you excatly this value:
raw_adc = AnalogRead(2)
then you can calculate the voltage from this:
float voltage = raw_adc/1023*(1.1)*(5.7));

Have you ever read the documentation and the examples for analogRead()?



Why do you declare this code as "working code"?
There is a single print statement:
serial.print ("solar panel voltage");
Which outputs a constant string. There is no way you see the result of the ADC conversion in your output. No wonder it is "working" :(

C:
if ( raw_adc>=1023){ // issue was here before i made it <=
digitalWrite (led, HIGH);
}
else{
digitalWrite (led, LOW);
}
Regardless of ">=" or "<" this statement makes no sense at all. As I tried to explain many times before: the raw ADC value is a number between 0 and 1023. Never higher.
So where your previous statement using <= was always true (LED always on), this statement using ">=" will never be true (LED always off).
Why and under which conditions do you want the LED to be on or off?

When you state that a particular code "doesn't work" you need to supply:
- expected behaviour (how it should work)
- real behaviour (what it does instead)
- relevant input data

Also: have you ever actually measured the voltage at the analog input pin (e.g. with a multimeter) and compared the measuerement with the output of your program? That will be the real world test.
Actually i did not see the output on serial monitor, i simply took it outside to test and it worked that time. Okay, as you said raw_adc = AnalogRead(2) i will check this command now.


have you ever actually measured the voltage at the analog input pin (e.g. with a multimeter) and compared the measurement with the output of your program? That will be the real world test.


Yes, i have made the following test.
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
You can do that, but what's the use of this?
analogRead() does give you excatly this value:
raw_adc = AnalogRead(2)
then you can calculate the voltage from this:
float voltage = raw_adc/1023*(1.1)*(5.7));

Have you ever read the documentation and the examples for analogRead()?



Why do you declare this code as "working code"?
There is a single print statement:
serial.print ("solar panel voltage");
Which outputs a constant string. There is no way you see the result of the ADC conversion in your output. No wonder it is "working" :(

C:
if ( raw_adc>=1023){ // issue was here before i made it <=
digitalWrite (led, HIGH);
}
else{
digitalWrite (led, LOW);
}
Regardless of ">=" or "<" this statement makes no sense at all. As I tried to explain many times before: the raw ADC value is a number between 0 and 1023. Never higher.
So where your previous statement using <= was always true (LED always on), this statement using ">=" will never be true (LED always off).
Why and under which conditions do you want the LED to be on or off?

When you state that a particular code "doesn't work" you need to supply:
- expected behaviour (how it should work)
- real behaviour (what it does instead)
- relevant input data

Also: have you ever actually measured the voltage at the analog input pin (e.g. with a multimeter) and compared the measuerement with the output of your program? That will be the real world test.
void loop() {
raw_adc = analogRead(2);

float voltage = (raw_adc/1023*(1.1)*(5.7));
serial.println (raw_adc);
serial.println (voltage);


delay(1000);

if ( voltage>=1023){ // issue was here before i made it <=
digitalWrite (led, HIGH);
}
else{
digitalWrite (led, LOW);
}
}





Hi i tried the code you suggested in the last post, it works but it is highly sensitive. Reads full on under my phone torch
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,098
Joined
Nov 17, 2011
Messages
13,098
f ( voltage>=1023){ // issue was here before i made it <=
digitalWrite (led, HIGH);
}
else{
digitalWrite (led, LOW);
}
You cant let go of this useless piece of code, can you?

it works but it is highly sensitive. Reads full on under my phone torch
That is not the code that is sensitive but photodetector/solar cell. Measure the output voltage of the solar cell when lit by the phone. Measure also the voltage at the analog input pin of the Arduino (after the resistive divider).
Thr truth is not in what you expect but in what the circuit physically does.
- Your solar cell may output more than 6 V (as it is possibly not loaded by a significant load current).
- Your voltage divider may be incorrect, delivering more than 1.1 V to the Arduino.
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
You cant let go of this useless piece of code, can you?


That is not the code that is sensitive but photodetector/solar cell. Measure the output voltage of the solar cell when lit by the phone. Measure also the voltage at the analog input pin of the Arduino (after the resistive divider).
Thr truth is not in what you expect but in what the circuit physically does.
- Your solar cell may output more than 6 V (as it is possibly not loaded by a significant load current).
- Your voltage divider may be incorrect, delivering more than 1.1 V to the Arduino.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
float voltage = (analogRead(A0)/1023 * (1.1) * (5.7));
int ADC_value = ADCL | (ADCH << 8);
Serial.print ("voltage at A0:");
Serial.println(voltage);
Serial.print ("Solar panel voltage:");
Serial.println(ADC_value);
delay (1000);
- Measure the output voltage of the solar cell when lit by the phone
0.8v-1.1v
-Measure also the voltage at the analog input pin of the Arduino (after the resistive divider)
0.6v-0.7v


In both the tests, voltage divider of 4.7k and 1k were used.
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
You cant let go of this useless piece of code, can you?


That is not the code that is sensitive but photodetector/solar cell. Measure the output voltage of the solar cell when lit by the phone. Measure also the voltage at the analog input pin of the Arduino (after the resistive divider).
Thr truth is not in what you expect but in what the circuit physically does.
- Your solar cell may output more than 6 V (as it is possibly not loaded by a significant load current).
- Your voltage divider may be incorrect, delivering more than 1.1 V to the Arduino.
another update, in order to reduce the current consumption i've changed my voltage dividers to 75k and 10k which would consume only 44uA whereas, old one(4.7k+1K) was consuming 0.6mA current (3.7/5.7).
 

electronoobb

Feb 11, 2023
26
Joined
Feb 11, 2023
Messages
26
1)
adc_lobyte = ADCL;
raw_adc = ADCH<<8 | adc_lobyte; // raw_adc should be declared as uint16_t

This command and:
2)
raw_adc = analogRead(2);
float voltage = (raw_adc/1023*(1.1)*(5.7));

Outputs are different

1) OUTPUT:
ADC reading:
42
41
48
50


2) OUTPUT:
ADC reading:

232
350
400
440

it will read 1023 under little light.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,098
Joined
Nov 17, 2011
Messages
13,098
adc_lobyte = ADCL;
raw_adc = ADCH<<8 | adc_lobyte; // raw_adc should be declared as uint16_t
This doesn't mean the analogRead() library function works incorrectly. It means your not using all the necessary code to cirumvent the library function (why you do this at this stage of your understanding the code I do not understand):
- Where in the code have you set up the ADC to read from Pin 2?
- Where have you set up the alignment of the output data?
You need to set up the ADC Multiplexer Selection Register correctly when accessing the ADC registers without using the library function.
All this is done by the Arduino analogRead() function so you don't have to care. If you want to bypass the library, you need to consider all relevant settings.
Throwing code in bits and pieces to me will not help create a common understanding.

it will read 1023 under little light.
This is not helpful. What you consider "little light" may already drive the solar cell to max. output voltage. Especially when the only load is the voltage divider. What you need to do is to establish the correspondence between actual voltage at the solar cell, the voltage at the Arduino's input pin and the output of your program. And this needs to be measured for different loads of the solar cell, e.g. no load, 1 mA load, 10 mA load, 30 mA load.
Do the measurements and create the table.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,098
Joined
Nov 17, 2011
Messages
13,098
- Measure the output voltage of the solar cell when lit by the phone
0.8v-1.1v
-Measure also the voltage at the analog input pin of the Arduino (after the resistive divider)
0.6v-0.7v
These measurements do not match the circuit in post #29 and the resistor values 1 k + 4.7 k. With these values as shown in post #29 the divider ratio is
[math] sc = \frac {1 k\Omega}{4.7 k\Omega + 1 k\Omega} = 0.175 [/math]An output voltage of the solar cell of 1.1 V should result in an input voltage of the Arduino of 0.193 V.
Are these measurements with a voltmeter or multimeter or are these numbers from your Arduino code? To verify the circuit and the code you need to compare true measurements with a meter to the output of the Arduino. Only this will allow you to judge the correctness of your code and your circuit.
 
Top