How to add sensor to the following code

Thread Starter

amishenglol

Joined Feb 27, 2023
1
Hi, I have a code that uses 1.1Vref (because the system is powered by battery) (ATTINY44A IC). I have connected one sensor to it and now i would like to read value of the sensor. Please check the code below.

This code uses internal reference voltage and outputs unchanged voltage rating.(THE code is for arduino and with little changes it will work for attiny)


void loop() {
//REFS1 AND REFS0 to 1 1 -> internal 1.1V refference
ADMUX |= B11000000; //We read A1 (MUX0)
ADMUX |= B00000001; // Start AD conversion
ADCSRA |= B11000000; // Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));
float val = ADCL | (ADCH << 8);
val = val * 5.7; Serial.println(val); }

from my perspective, in order to read sensor value the code should be:

int sensorVoltage = analogRead (A0);
val = (val * 5.7); val = (val/1024);
val = (val*sensorVoltage);
if (voltage<=2000){ //3V
DO SOMETHING
}


Unfortunately, the above code does not work as needed.

for example, if the sensor at 3v reads 2000 then it should be something like if (sensorvalue<=2000){do something};
But what if with some other battery little less or little more charged, the sensor does not read 2000 or reads some value greater than 2000 at 3v then what is the solution to it?

The value changes with battery voltage.

The code works alright with arduino but when i transfer it to attiny it does not work properly for instance, arduino reads 2000 at 3v whereas, attiny does not read 2000 at 3-3.4V.
 

Irving

Joined Jan 30, 2016
4,005
Your code:

int sensorVoltage = analogRead (A0);
val = (val * 5.7); val = (val/1024);
val = (val*sensorVoltage);
if (voltage<=2000){ //3V
DO SOMETHING
}

This code makes no sense.... you read the ADC with analogRead into sensorVoltage, then you play around with 'val' which is apparently an unset variable resulting in an unknown value, the you multiply the two together giving an unknown result!

analogRead() on Arduino defaults reference to Vcc at either 3.3v or 5v depending on which board you are using. Again, depending on board, resolution available is either 10bit (1024) or 12bit (4096), but default is always 1024. Assuming 3.3v ref and 10bit, the code for an Arduino will be:


int val = analogRead(A0); // 0= 0v, 1024 = 3.3v
float sensorVoltage = (val * 3.3)/1024.0;
if(sensorVoltage < 3.0) {
// do something
}


However its better not to convert to floating point unless you need the actual value elsewhere


int val = analogRead(A0); // 0= 0v, 1024 = 3.3v
if(val< 0x3A3) { // 0x3A3 = 931 = 3.0/3.3*1024
// do something
}


Now, if you need to use the 1.1v ref you cannot read a 3v input. When REF is set to 1.1v the max reading of the 10bit ADC = 0x3ff (1023) = 1.1v, With a 3v input the result will always be 0x3FF. As per the datasheet for ATTinyy44:
"16.11.1 Single Ended Conversion​
For single ended conversion, the result is​
\( ADC = V_{IN} . 1024/V_{REF} \)​
where \(V_{IN} \) is the voltage on the selected input pin and \(V_{REF} \) the selected voltage reference (see
Table 16-3 on page 145 and Table 16-4 on page 146). 0x000 represents analog ground, and​
0x3FF represents the selected reference voltage minus one LSB. The result is presented in one-​
sided form, from 0x3FF to 0x000. "​

The same is true for the ATMega328 processor on the Arduino.

You'll need to use a potential divider on the analog input to reduce the voltage below 1.1v, so that full battery volts, say 3.3v is 1.0v, then 3v will be around 856 or 0x358

1677508300708.png

And your code will be:


analogReference(INTERNAL);
int val = analogRead(A0); // 0= 0v, 1024 = 1.1v or an equivalent battery voltage of 1.1*39/12 = 3.58v
if(val< 0x358) { 0x358 = 856/1024*3.58=2.99v
// do something
}
 
Last edited:

amishlol234

Joined Mar 10, 2022
32
Hi,
Thanks alot for the response. finally i got some idea. I have one question, my battery voltage is 3.7-4.2V and it will deplete overtime so i need a voltage divider over there as well, what i did is, i have used 4.7k and 1k divider at battery side to reduce it below 1.1V and it reads around 0.5-0.6V respectively. My main concern is to read sensor voltage. i did not understand how you took the val 856 and in the end code you multiplied 1.1 by 39 from where you got 39?
 

amishlol234

Joined Mar 10, 2022
32
Your code:

int sensorVoltage = analogRead (A0);
val = (val * 5.7); val = (val/1024);
val = (val*sensorVoltage);
if (voltage<=2000){ //3V
DO SOMETHING
}

This code makes no sense.... you read the ADC with analogRead into sensorVoltage, then you play around with 'val' which is apparently an unset variable resulting in an unknown value, the you multiply the two together giving an unknown result!

analogRead() on Arduino defaults reference to Vcc at either 3.3v or 5v depending on which board you are using. Again, depending on board, resolution available is either 10bit (1024) or 12bit (4096), but default is always 1024. Assuming 3.3v ref and 10bit, the code for an Arduino will be:


int val = analogRead(A0); // 0= 0v, 1024 = 3.3v
float sensorVoltage = (val * 3.3)/1024.0;
if(sensorVoltage < 3.0) {
// do something
}


However its better not to convert to floating point unless you need the actual value elsewhere


int val = analogRead(A0); // 0= 0v, 1024 = 3.3v
if(val< 0x3A3) { // 0x3A3 = 931 = 3.0/3.3*1024
// do something
}


Now, if you need to use the 1.1v ref you cannot read a 3v input. When REF is set to 1.1v the max reading of the 10bit ADC = 0x3ff (1023) = 1.1v, With a 3v input the result will always be 0x3FF. As per the datasheet for ATTinyy44:
"16.11.1 Single Ended Conversion​
For single ended conversion, the result is​
\( ADC = V_{IN} . 1024/V_{REF} \)​
where \(V_{IN} \) is the voltage on the selected input pin and \(V_{REF} \) the selected voltage reference (see
Table 16-3 on page 145 and Table 16-4 on page 146). 0x000 represents analog ground, and​
0x3FF represents the selected reference voltage minus one LSB. The result is presented in one-​
sided form, from 0x3FF to 0x000. "​

The same is true for the ATMega328 processor on the Arduino.

You'll need to use a potential divider on the analog input to reduce the voltage below 1.1v, so that full battery volts, say 3.3v is 1.0v, then 3v will be around 856 or 0x358

View attachment 288507

And your code will be:


analogReference(INTERNAL);
int val = analogRead(A0); // 0= 0v, 1024 = 1.1v or an equivalent battery voltage of 1.1*39/12 = 3.58v
if(val< 0x358) { 0x358 = 856/1024*3.58=2.99v
// do something
}



Hi,
Thanks alot for the response. finally i got some idea. I have one question, my battery voltage is 3.7-4.2V and it will deplete overtime so i need a voltage divider over there as well, what i did is, i have used 4.7k and 1k divider at battery side to reduce it below 1.1V and it reads around 0.5-0.6V respectively. My main concern is to read sensor voltage. i did not understand how you took the val 856 and in the end code you multiplied 1.1 by 39 from where you got 39?
 

Irving

Joined Jan 30, 2016
4,005
Hi,
Thanks alot for the response. finally i got some idea. I have one question, my battery voltage is 3.7-4.2V and it will deplete overtime so i need a voltage divider over there as well, what i did is, i have used 4.7k and 1k divider at battery side to reduce it below 1.1V and it reads around 0.5-0.6V respectively. My main concern is to read sensor voltage. i did not understand how you took the val 856 and in the end code you multiplied 1.1 by 39 from where you got 39?
The output of a voltage divider Vo is:

[eq1] Vo = Vin . R2/(R1 + R2)


Using the values in my diagram in post#2, 3v in gives Vo = 3 * 12k/(12k+27k) = 3 * 12/39 = 0.92v

to find out what Vin gives a required Vo you rearrange the formula:

[eq 2] Vin = Vo . (R1 + R2)/R1

so the maximum input voltage that can be measured that way is:

Vin = 1.1 * (12k+27k)/12k = 1.1 * 39/12 = 3.58v

So now we know that - in my example - 3.58v will give a reading of 1.1v or 0x3FF (1023) on the ADC. The actual ADC output for a given input voltage to the divider we know is:

[eq 3] ADCout = Vin . 1024/ Vref

Combining Eq 1 and Eq 3 we get:

[eq 4] ADCout = Vin . R2/(R1 + R2) . 1024/Vref

So a 3v input gives an ADC reading of ADCout = 3 . 12/(12+ 27) . 1024/1.1 = 859 or 0x35B (note, this is slightly higher than the 856/0x358 given earlier because doing it all in one go eliminates rounding errors. Its within 10.5mV however).

A LiPo battery when fully charged will read 4.2v but will rapidly drop in the first few minutes of use to 3.7v and then slowly drop to the terminal voltage, typically taken as 2.9v or 2.95v. Unless there is a good reason to measure over the whole range I wouldn't worry about voltages above 3.7v. Using 1k and 4.7k gives, from eq 2 a maximum Vin value of 1.1 *5.7/1 = 6.27v, with 3v coming in at 0.526v (490/0x1EA) which is wasteful of the dynamic range. Also those low values draw 700uA from the battery which is potentially a significant amount - you should increase them by a factor of 10 (10k & 47k) at least. I'd use 10k and 30k to give an upper value of 4.4v.

Hope that helps.
 

amishlol234

Joined Mar 10, 2022
32
The output of a voltage divider Vo is:

[eq1] Vo = Vin . R2/(R1 + R2)


Using the values in my diagram in post#2, 3v in gives Vo = 3 * 12k/(12k+27k) = 3 * 12/39 = 0.92v

to find out what Vin gives a required Vo you rearrange the formula:

[eq 2] Vin = Vo . (R1 + R2)/R1

so the maximum input voltage that can be measured that way is:

Vin = 1.1 * (12k+27k)/12k = 1.1 * 39/12 = 3.58v

So now we know that - in my example - 3.58v will give a reading of 1.1v or 0x3FF (1023) on the ADC. The actual ADC output for a given input voltage to the divider we know is:

[eq 3] ADCout = Vin . 1024/ Vref

Combining Eq 1 and Eq 3 we get:

[eq 4] ADCout = Vin . R2/(R1 + R2) . 1024/Vref

So a 3v input gives an ADC reading of ADCout = 3 . 12/(12+ 27) . 1024/1.1 = 859 or 0x35B (note, this is slightly higher than the 856/0x358 given earlier because doing it all in one go eliminates rounding errors. Its within 10.5mV however).

A LiPo battery when fully charged will read 4.2v but will rapidly drop in the first few minutes of use to 3.7v and then slowly drop to the terminal voltage, typically taken as 2.9v or 2.95v. Unless there is a good reason to measure over the whole range I wouldn't worry about voltages above 3.7v. Using 1k and 4.7k gives, from eq 2 a maximum Vin value of 1.1 *5.7/1 = 6.27v, with 3v coming in at 0.526v (490/0x1EA) which is wasteful of the dynamic range. Also those low values draw 700uA from the battery which is potentially a significant amount - you should increase them by a factor of 10 (10k & 47k) at least. I'd use 10k and 30k to give an upper value of 4.4v.

Hope that helps.
Thanks for that deep explanation. see my max val is 6.27v so if i want to read any in between voltages then what would i write?
 

amishlol234

Joined Mar 10, 2022
32
The output of a voltage divider Vo is:

[eq1] Vo = Vin . R2/(R1 + R2)


Using the values in my diagram in post#2, 3v in gives Vo = 3 * 12k/(12k+27k) = 3 * 12/39 = 0.92v

to find out what Vin gives a required Vo you rearrange the formula:

[eq 2] Vin = Vo . (R1 + R2)/R1

so the maximum input voltage that can be measured that way is:

Vin = 1.1 * (12k+27k)/12k = 1.1 * 39/12 = 3.58v

So now we know that - in my example - 3.58v will give a reading of 1.1v or 0x3FF (1023) on the ADC. The actual ADC output for a given input voltage to the divider we know is:

[eq 3] ADCout = Vin . 1024/ Vref

Combining Eq 1 and Eq 3 we get:

[eq 4] ADCout = Vin . R2/(R1 + R2) . 1024/Vref

So a 3v input gives an ADC reading of ADCout = 3 . 12/(12+ 27) . 1024/1.1 = 859 or 0x35B (note, this is slightly higher than the 856/0x358 given earlier because doing it all in one go eliminates rounding errors. Its within 10.5mV however).

A LiPo battery when fully charged will read 4.2v but will rapidly drop in the first few minutes of use to 3.7v and then slowly drop to the terminal voltage, typically taken as 2.9v or 2.95v. Unless there is a good reason to measure over the whole range I wouldn't worry about voltages above 3.7v. Using 1k and 4.7k gives, from eq 2 a maximum Vin value of 1.1 *5.7/1 = 6.27v, with 3v coming in at 0.526v (490/0x1EA) which is wasteful of the dynamic range. Also those low values draw 700uA from the battery which is potentially a significant amount - you should increase them by a factor of 10 (10k & 47k) at least. I'd use 10k and 30k to give an upper value of 4.4v.

Hope that helps.

Hi,


void setup() {
// put your setup code here, to run once:
Serial.begin (115200);
}

void loop() {
// put your main code here, to run repeatedly:
analogReference (INTERNAL);
int val = analogRead (A0);
if ( val <=0x627){
Serial.println ("i am reading");
Serial.println(val);
delay(1000);
}
}



this is the code that i wrote. I have attached output file from serial monitor along with the circuit. Please check and let me know. My another question would be, don't we need to measure battery voltage because as per the voltage formula int sensorVal = (Vref* val)/1024. The vref will be the battery voltage which must not change. Is that so, or my concept is wrong?
 

Attachments

amishlol234

Joined Mar 10, 2022
32
The output of a voltage divider Vo is:

[eq1] Vo = Vin . R2/(R1 + R2)


Using the values in my diagram in post#2, 3v in gives Vo = 3 * 12k/(12k+27k) = 3 * 12/39 = 0.92v

to find out what Vin gives a required Vo you rearrange the formula:

[eq 2] Vin = Vo . (R1 + R2)/R1

so the maximum input voltage that can be measured that way is:

Vin = 1.1 * (12k+27k)/12k = 1.1 * 39/12 = 3.58v

So now we know that - in my example - 3.58v will give a reading of 1.1v or 0x3FF (1023) on the ADC. The actual ADC output for a given input voltage to the divider we know is:

[eq 3] ADCout = Vin . 1024/ Vref

Combining Eq 1 and Eq 3 we get:

[eq 4] ADCout = Vin . R2/(R1 + R2) . 1024/Vref

So a 3v input gives an ADC reading of ADCout = 3 . 12/(12+ 27) . 1024/1.1 = 859 or 0x35B (note, this is slightly higher than the 856/0x358 given earlier because doing it all in one go eliminates rounding errors. Its within 10.5mV however).

A LiPo battery when fully charged will read 4.2v but will rapidly drop in the first few minutes of use to 3.7v and then slowly drop to the terminal voltage, typically taken as 2.9v or 2.95v. Unless there is a good reason to measure over the whole range I wouldn't worry about voltages above 3.7v. Using 1k and 4.7k gives, from eq 2 a maximum Vin value of 1.1 *5.7/1 = 6.27v, with 3v coming in at 0.526v (490/0x1EA) which is wasteful of the dynamic range. Also those low values draw 700uA from the battery which is potentially a significant amount - you should increase them by a factor of 10 (10k & 47k) at least. I'd use 10k and 30k to give an upper value of 4.4v.

Hope that helps.



Hi, Another code that i have been using is:

int led = 8;

void setup(){
Serial.begin(9600);
pinMode (led,OUTPUT);
}

void loop() {
//REFS1 AND REFS0 to 1 1 -> internal 1.1V refference
ADMUX |= B11000000;
//We read A1 (MUX0)
ADMUX |= B00000001;
//int sensor = analogRead(A1);
// Start AD conversion
ADCSRA |= B11000000;
// Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));
float val = ADCL | (ADCH << 8);
val = val * 5.7; //Multiply by the inverse of the divider
Serial.println(val);

float voltage = val * analogRead(A0) / 1023;
voltage = ADCL | (ADCH << 8);
Serial.print ("voltage at A0:");
Serial.println(voltage);
Serial.print ("Solar panel voltage:");
Serial.println(voltage * 5.7);
delay(1000);

if (voltage>=15){ //1.1V
digitalWrite (led,HIGH);
}
else{
digitalWrite(led,LOW);
}
}


schematic attached below.



it reads accurate value when the positive side of the divider is left free.

2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2741.70
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
1026.00
voltage at A0:10.00


The moment i connect it to battery (has to go to battery for charging it during the daytime).

olar panel voltage:609.90
969.00
voltage at A0:107.00
Solar panel voltage:609.90
969.00
voltage at A0:107.00
Solar panel voltage:609.90
969.00
voltage at A0:107.00
Solar panel voltage:609.90
969.00
voltage at A0:106.00
Solar panel voltage:604.20
957.60
voltage at A0:107.00
Solar panel voltage:609.90
957.60
voltage at A0:106.00
Solar panel voltage:604.20
957.60
voltage at A0:106.00
Solar panel voltage:604.20
957.60
voltage at A0:106.00
Solar panel voltage:604.20

The solar panel stops working, can't read 0v or any number greater than 107
 

Attachments

Irving

Joined Jan 30, 2016
4,005
this is the code that i wrote. I have attached output file from serial monitor along with the circuit. Please check and let me know. My another question would be, don't we need to measure battery voltage because as per the voltage formula int sensorVal = (Vref* val)/1024. The vref will be the battery voltage which must not change. Is that so, or my concept is wrong?
Your circuit is wrong, the diode D1 is back-to-front - as drawn the reading read from A0 will generally be close to 0 with some random noise as shown by output file. Assuming D1 was other way round the voltage measured would be:

(5v - Vf(D1)) . 1/5.7 = 4.4 / 5.7 = 0.772v or a reading of 719 (0x2CF)


Re code, a minor change and a comment

C:
void setup() {
    // put your setup code here, to run once:

    Serial.begin (115200);
    analogReference (INTERNAL); // only needs to be done once
}

void loop() {
    // put your main code here, to run repeatedly:

    int val = analogRead (A0);  // gets a value referenced to the internal Vref of 1.1v, where 0x3FF = 1.1v at A0
    if ( val <=0x627){   //0x627 is not possible, 10bit ADC on Arduino only gives range 0x0 - 0x3FF, so this is always TRUE
        Serial.println ("i am reading");
        Serial.println(val);
        delay(1000);
    }
}
 

amishlol234

Joined Mar 10, 2022
32
yes, you right,it is because of the direction, i realized it after some time and removed it from my board. ok, so your code is working but i have a confusion pleeeeeeeeaaaaaaaseeeeee answer it ive asked about it on several forums but nobody has answered it properly. see i followed a link (http://electronoobs.com/eng_arduino_tut156.php) as per this link if we want to measure accurate sensor voltage we first need to have a constant battery voltage so that it can be substituted as a constant in the voltage formula which is = (int sensorVal = (batt voltage* ADCval)/1024); so we are using 1.1v our formula should be int sensorVal = (1.1* ADCval)/1024; correct? or do we really need to measure battery voltage as constant and use it in our formula.

As i can see in your code you have not used any voltage calculation formula but still the code works.
Please clarify. Thank you in advance.
 

Irving

Joined Jan 30, 2016
4,005
yes, you right,it is because of the direction, i realized it after some time and removed it from my board. ok, so your code is working but i have a confusion pleeeeeeeeaaaaaaaseeeeee answer it ive asked about it on several forums but nobody has answered it properly. see i followed a link (http://electronoobs.com/eng_arduino_tut156.php) as per this link if we want to measure accurate sensor voltage we first need to have a constant battery voltage so that it can be substituted as a constant in the voltage formula which is = (int sensorVal = (batt voltage* ADCval)/1024); so we are using 1.1v our formula should be int sensorVal = (1.1* ADCval)/1024; correct? or do we really need to measure battery voltage as constant and use it in our formula.

As i can see in your code you have not used any voltage calculation formula but still the code works.
Please clarify. Thank you in advance.
If you are using the INTERNAL reference you do not need to worry about/use VDD (supply) voltage in calculations, you use Vref of 1.1v instead. The supply voltage stability only applies when using DEFAULT reference which makes Vref = chip's VDD input. So:

float sensorVal = (1.1* ADCval)/1024;​

is correct.

Hi, Another code that i have been using is:

int led = 8;

void setup(){
Serial.begin(9600);
pinMode (led,OUTPUT);
}

void loop() {
//REFS1 AND REFS0 to 1 1 -> internal 1.1V refference
ADMUX |= B11000000;
//We read A1 (MUX0)
ADMUX |= B00000001;
//int sensor = analogRead(A1);
// Start AD conversion
ADCSRA |= B11000000;
// Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));
float val = ADCL | (ADCH << 8);
val = val * 5.7; //Multiply by the inverse of the divider
Serial.println(val);

float voltage = val * analogRead(A0) / 1023;
voltage = ADCL | (ADCH << 8);
Serial.print ("voltage at A0:");
Serial.println(voltage);
Serial.print ("Solar panel voltage:");
Serial.println(voltage * 5.7);
delay(1000);

if (voltage>=15){ //1.1V
digitalWrite (led,HIGH);
}
else{
digitalWrite(led,LOW);
}
}


schematic attached below.



it reads accurate value when the positive side of the divider is left free.

2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2741.70
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
2747.40
voltage at A0:10.00
Solar panel voltage:57.00
1026.00
voltage at A0:10.00


The moment i connect it to battery (has to go to battery for charging it during the daytime).

olar panel voltage:609.90
969.00
voltage at A0:107.00
Solar panel voltage:609.90
969.00
voltage at A0:107.00
Solar panel voltage:609.90
969.00
voltage at A0:107.00
Solar panel voltage:609.90
969.00
voltage at A0:106.00
Solar panel voltage:604.20
957.60
voltage at A0:107.00
Solar panel voltage:609.90
957.60
voltage at A0:106.00
Solar panel voltage:604.20
957.60
voltage at A0:106.00
Solar panel voltage:604.20
957.60
voltage at A0:106.00
Solar panel voltage:604.20

The solar panel stops working, can't read 0v or any number greater than 107

Phew... where to begin...

Your solar circuit makes no sense. can you draw full circuit with battery and solar panel. Both battery -ve and solar panel -ve must connect to common ground else nothing works right.

I think what you mean code-wise is:

C:
void loop() {
//REFS1 AND REFS0 to 1 1 -> internal 1.1V reference
ADMUX |= B11000000;
//We read A1 (MUX0)
ADMUX |= B00000001;
//int sensor = analogRead(A1);
// Start AD conversion
ADCSRA |= B11000000;
// Detect end-of-conversion
while (bit_is_set(ADCSRA,ADSC));

// don't use analogRead if you are using above code - all it does is same as above!
// use multiple variables to keep things simple. Don't keep reusing until you are 100% its working right.

int rawADC = ADCL | (ADCH << 8);

float voltageA0= (1.1 * rawADC )/1024 ; // actual voltage at A0, but note MUX selection above is for A1?
Serial.print ("Voltage at A0: ");
Serial.println(voltageA0);

float solarVoltage= voltageA0 * 5.7; //Multiply by the inverse of the divider to get actual voltage at divider
Serial.print("Solar voltage: ");
Serial.println(solarVoltage);

delay(1000);

// no idea what you were trying to do here
if (voltage>=15){  //1.1V
digitalWrite (led,HIGH);
}
else{
digitalWrite(led,LOW);
}
}
 

amishlol234

Joined Mar 10, 2022
32
The Nominal voltage is 6V of my solar panel
Yes the circuit you have shared is correct, that is what I want to do.


You said
Are you trying to do something like this?

What is your solar panel's nominal voltage?

View attachment 288664



Yes, you are 100% right about the circuit but what's the diode shaped thing in btwn I don't have that connected.

Yes, I have shorted all grounds together.

The Nominal voltage of solar panel is 6v,30mA.

Your circuit is absolutely correct.

The code you just wrote above, I'll give it a try. Thank you, I've been to several forums nobody understood my circuit or logic like you, I hope we can get through it together :)
 

Irving

Joined Jan 30, 2016
4,005
Yes, you are 100% right about the circuit but what's the diode shaped thing in btwn I don't have that connected.
Most chargers are buck converters that often don't like having battery connected with no input power. The diode stops the battery feeding back into the charger (or, if you prefer, stops the battery being shorted out by the charger).

What charger board are you using? Link to it?

What is this going to power? What's your power budget? Because that solar cell may struggle keeping the battery sufficiently charged.
 

amishlol234

Joined Mar 10, 2022
32
Most chargers are buck converters that often don't like having battery connected with no input power. The diode stops the battery feeding back into the charger (or, if you prefer, stops the battery being shorted out by the charger).

What charger board are you using? Link to it?

What is this going to power? What's your power budget? Because that solar cell may struggle keeping the battery sufficiently charged.
Actually I don't have any charger circuit connected to it. The battery charges only during the day time so it is impossible to for the charge to go beyond 4.2. That's why I don't have any charging circuit in between and currently I don't even need it maybe in the future if needed I'd think about it but as per my experiments of battery charging with this solar panel, it takes almost 2 days to come around 4.1v. So yes, that's not my concern. What do you think, the rest of the circuit connections are OK? Or has some issue or coding issue?
 

amishlol234

Joined Mar 10, 2022
32
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
pinMode (led, OUTPUT);
analogReference (INTERNAL);
}

void loop() {
// put your main code here, to run repeatedly:
float voltage = (analogRead(2)/1023*(1.1)*(5.7));
int ADC_value = ADCL | (ADCH<<8);
Serial.print ("solar panel voltage");
Serial.println(ADC_value);
delay(1000);
}

This code has helped me, it worked. Now my question is:

1677742904121.png

can i charge my battery like this? because if i connect solar + to battery +, the solar always reads 1023 which i don't want.
 

Attachments

Last edited:

amishlol234

Joined Mar 10, 2022
32
Most chargers are buck converters that often don't like having battery connected with no input power. The diode stops the battery feeding back into the charger (or, if you prefer, stops the battery being shorted out by the charger).

What charger board are you using? Link to it?

What is this going to power? What's your power budget? Because that solar cell may struggle keeping the battery sufficiently charged.

Just an update, the code works perfectly for arduino but not for attiny and therefore, i had to edit a few lines but unfortunately it is still not working as needed.

Code:
int led = 3;
#define solar  2
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
pinMode (led, OUTPUT);
pinMode (solar, INPUT);
//analogReference (INTERNAL);
}

void loop() {
//  ADMUX = (1 << REFS1) | (0 << REFS0) ;  // Sets ref. voltage to internal
  analogReference (INTERNAL);
  int sensor = analogRead(solar);
  float voltage = (sensor/1023*(1.1)*(5.7));
  ADCSRB = (1 << ADLAR);
  int ADC_value = ADCL | (ADCH<<8);
  Serial.print ("solar panel voltage");
  Serial.println(ADC_value);

  delay(1000);

  if (ADC_value<=1023){
    digitalWrite (led, HIGH);
  }
  else{
        digitalWrite (led, LOW);

  }
}
it's attiny44
can you point out error?

Moderators note : Please use code tags for pieces of code.
 
Last edited by a moderator:

Irving

Joined Jan 30, 2016
4,005
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
pinMode (led, OUTPUT);
analogReference (INTERNAL);
}

void loop() {
// put your main code here, to run repeatedly:
float voltage = (analogRead(2)/1023*(1.1)*(5.7));
int ADC_value = ADCL | (ADCH<<8);
Serial.print ("solar panel voltage");
Serial.println(ADC_value);
delay(1000);
}

This code has helped me, it worked. Now my question is:

View attachment 288747

can i charge my battery like this? because if i connect solar + to battery +, the solar always reads 1023 which i don't want.
Hmmm, is the microcontroller directly connected to the battery - no voltage regulator in between?
When you connect the two together, is the panel in darkness or light? What is the solar panel +ve voltage a) before connecting and b) after connecting, in both darkness and light.
 

Irving

Joined Jan 30, 2016
4,005
Just an update, the code works perfectly for arduino but not for attiny and therefore, i had to edit a few lines but unfortunately it is still not working as needed.

Code:
int led = 3;
#define solar  2
void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
pinMode (led, OUTPUT);
pinMode (solar, INPUT);
//analogReference (INTERNAL);
}

void loop() {
//  ADMUX = (1 << REFS1) | (0 << REFS0) ;  // Sets ref. voltage to internal
  analogReference (INTERNAL);
  int sensor = analogRead(solar);
  float voltage = (sensor/1023*(1.1)*(5.7));
  ADCSRB = (1 << ADLAR);
  int ADC_value = ADCL | (ADCH<<8);
  Serial.print ("solar panel voltage");
  Serial.println(ADC_value);

  delay(1000);

  if (ADC_value<=1023){
    digitalWrite (led, HIGH);
  }
  else{
        digitalWrite (led, LOW);

  }
}
it's attiny44
can you point out error?

Moderators note : Please use code tags for pieces of code.
Try this - Don't mix analogRead and direct register access, you don't know what side effects occur. Keep code clean, don't intermingle stuff, it makes it hard to understand
This tests whether analogRead works on ATTiny44. BTW how are you programming the ATTiny44 and are you using the Arduino IDE?

Code:
int led = 3;
#define solar  A0
#define battery A1

void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
pinMode (led, OUTPUT);
pinMode (solar, INPUT);
pinMode(batteryy, INPUT);
analogReference (INTERNAL);
}

void loop() {

  int ADC_A0 = analogRead(solar);
  float A0Voltage = (ADC_A0 *1.1)/1024;
  float solarVoltage = A0Voltage * 5.7;
  Serial.print ("ADC A0 = ");
  Serial.println(ADC_A0 );
  Serial.print ("A0Voltage  = ");
  Serial.println(A0Voltage );
  Serial.print ("solarVoltage  = ");
  Serial.println(solarVoltage );

  int ADC_A1 = analogRead(battery);
  float A1Voltage = (ADC_A1 * 1.1)/1024;
  float batteryVoltage = A1Voltage * 5.7;
  Serial.print ("ADC_A1 = ");
  Serial.println(ADC_A1 );
  Serial.print ("A1Voltage  = ");
  Serial.println(A1Voltage );
  Serial.print ("batteryVoltage = ");
  Serial.println(batteryVoltage );


  delay(1000);

  if (ADC_A0 <=1023){
    digitalWrite (led, HIGH);
  }
  else{
        digitalWrite (led, LOW);

  }
}
 
Top