ladyada's portable solar charging tracker issues

Hi everybody,

I was trying to put together ladyada’s portable solar charging tracker that you can find here: Quickie Projects - Portable solar charging tracker.

I am having difficulties with the sketch as I expect 0 (zero) values (or some fluctuating values) printed via the Serial.print (with nothing connected to the Arduino) and I get some specific values that never change whatever I do. I always get:

1023
LiPo voltage = 5.49
PV voltage = 6.59
Current (mA) = 685.73

As I try to figure out the sketch I stumbled on a few things I really don’t understand. For example, what does *= and /= stand for? As in:

  float lipoV = adcreading;
  lipoV *= aref_voltage;
  lipoV /= 1024;
  lipoV *= lipoMult;

But anyway can somebody test the sketch and give me some ideas why it is not working or how it should work?

A big thank you!!

/* 
Portable solar panel efficiency tracker. For testing out solar panels!
See http://www.ladyada.net/make/solarlogger for more information

Code is public domain, enjoy! 
*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7, 8);

#define aref_voltage 3.3         // we tie 3.3V to ARef and measure it with a multimeter!

int lipoPin = 3;      // the battery 
float lipoMult = 1.666;  // how much to multiply to get the original voltage

int PVPin = 2;      // the cell
float PVMult = 2;  // how much to multiply to get the original voltage

int currentPin = 1;
float currentMult = 208; // how much to multiply to get the original current draw
    
void setup(void) {
  // We'll send debugging information via the Serial monitor
  Serial.begin(9600);   
  
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 2);
  lcd.clear();
  // Print a message to the LCD.
  lcd.print("Solar logger");
  delay(2000);
  lcd.clear();
  // If you want to set the aref to something other than 5v
  analogReference(EXTERNAL);
  
  byte delta[8] = {
	B00000,
	B00100,
	B00100,
	B01010,
	B01010,
	B10001,
	B11111,
	B00000
};

  lcd.createChar(0, delta);
}



void loop(void) {
  int adcreading;
 
  adcreading = analogRead(lipoPin);  
  Serial.println(adcreading);
  
  float lipoV = adcreading;
  lipoV *= aref_voltage;
  lipoV /= 1024;
  lipoV *= lipoMult;

  lcd.clear();
  Serial.print("LiPo voltage = ");
  Serial.println(lipoV);     // the raw analog reading
  
  lcd.setCursor(0, 0);
  lcd.print("LiPo=");
  lcd.print(lipoV);
  lcd.print(' ');
  lcd.write(0);
  
  adcreading = analogRead(PVPin);  
  float PVV = adcreading;
  PVV *= aref_voltage;
  PVV /= 1024;
  PVV *= PVMult;
  
  lcd.print((int)((PVV-lipoV) * 1000), DEC);  // in mV
  lcd.print("mV");
  
  Serial.print("PV voltage = ");
  Serial.println(PVV);     // the raw analog reading

  lcd.setCursor(0, 1);
  lcd.print("PV=");
  lcd.print(PVV);
  
  adcreading = analogRead(currentPin);  
  float currentI = adcreading;
  currentI *= aref_voltage;
  currentI /= 1024;
  currentI *= currentMult;
  Serial.print("Current (mA) = ");
  Serial.println(currentI);     // the raw analog reading
  
  lcd.print(" I=");
  lcd.print((int)currentI);
  lcd.print("mA");
  delay(1000);
}

as I expect 0 (zero) values (or some fluctuating values) printed via the Serial.print (with nothing connected to the Arduino) and I get some specific values that never change whatever I do. I always get:

So, your expectations are wrong. Reading from a pin with nothing connected to it is undefined behavior. You can not expect the results to be any particular value or range of values.

The *= and /= are shorthand i = i * 5; can be written as i *= 5;

These are documented on the reference page.

Wow, you’re fast!

Thank you so much, Paul!

As I said I expect it to behave randomly. What amazes me is that it always outputs the same number: 1023.
I tried modifying the sketch just as much as to bring it close to what I know (using a pot as an analog input instead of letting it flow). And something as easy as this which works as expected:

int potPin = 3;    // select the input pin for the potentiometer
int val = 0;       // variable to store the value coming from the sensor

void setup() {

  Serial.begin (9600);
}

void loop() {
  val = analogRead(potPin);    // read the value from the sensor
  Serial.println (val);
}

does not work in this modified sketch where I changed 4 lines of code to just simulate the pot sketch:

int potPin = 3;      // !!!!!!! it used to be: int lipoPin = 3; !!!!!!!!!
int val = 0; // !!!!!!!!!added this value !!!!!!!!!

and

val = analogRead(potPin);  // !!!!!! it used to be: adcreading = analogRead(lipoPin); !!!!!
  Serial.println(val);  // !!!!!! it used to be: Serial.println(adcreading); !!!!!!!!

I know you might find it messy but I am trying to demonstrate a point! In this newly modified sketch I still get 1023 in the Serial.print and I can’t change it with the pot. It drives me nuts! (I changed the names of the values so I would know for sure I am not referencing them somewhere else.)

/* 
Portable solar panel efficiency tracker. For testing out solar panels!
See http://www.ladyada.net/make/solarlogger for more information

Code is public domain, enjoy! 
*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7, 8);

#define aref_voltage 3.3         // we tie 3.3V to ARef and measure it with a multimeter!

int potPin = 3;      // !!!!!!! it used to be: int lipoPin = 3; !!!!!!!!!
int val = 0; // !!!!!!!!!added this value !!!!!!!!!


float lipoMult = 1.666;  // how much to multiply to get the original voltage

int PVPin = 2;      // the cell
float PVMult = 2;  // how much to multiply to get the original voltage

int currentPin = 1;
float currentMult = 208; // how much to multiply to get the original current draw
    
void setup() {
  // We'll send debugging information via the Serial monitor
  Serial.begin(9600);   
  
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 2);
  lcd.clear();
  // Print a message to the LCD.
  lcd.print("Solar logger");
  delay(2000);
  lcd.clear();
  // If you want to set the aref to something other than 5v
  analogReference(EXTERNAL);
  
  byte delta[8] = {
	B00000,
	B00100,
	B00100,
	B01010,
	B01010,
	B10001,
	B11111,
	B00000
};

  lcd.createChar(0, delta);
}



void loop() {
  int adcreading;
 
  val = analogRead(potPin);  // !!!!!! it used to be: adcreading = analogRead(lipoPin); !!!!!
  Serial.println(val);  // !!!!!! it used to be: Serial.println(adcreading); !!!!!!!!
  
  float lipoV = adcreading;
  lipoV *= aref_voltage;
  lipoV /= 1024;
  lipoV *= lipoMult;

  lcd.clear();
  Serial.print("LiPo voltage = ");
  Serial.println(lipoV);     // the raw analog reading
  
  lcd.setCursor(0, 0);
  lcd.print("LiPo=");
  lcd.print(lipoV);
  lcd.print(' ');
  lcd.write(0);
  
  adcreading = analogRead(PVPin);  
  float PVV = adcreading;
  PVV *= aref_voltage;
  PVV /= 1024;
  PVV *= PVMult;
  
  lcd.print((int)((PVV-lipoV) * 1000), DEC);  // in mV
  lcd.print("mV");
  
  Serial.print("PV voltage = ");
  Serial.println(PVV);     // the raw analog reading

  lcd.setCursor(0, 1);
  lcd.print("PV=");
  lcd.print(PVV);
  
  adcreading = analogRead(currentPin);  
  float currentI = adcreading;
  currentI *= aref_voltage;
  currentI /= 1024;
  currentI *= currentMult;
  Serial.print("Current (mA) = ");
  Serial.println(currentI);     // the raw analog reading
  
  lcd.print(" I=");
  lcd.print((int)currentI);
  lcd.print("mA");
  delay(1000);
}

I am guessing something else is influencing the result… but what? :~

I googled for *= and /= with no avail! Thank you so much for your help! I learned about this. I should have known them!

The difference between the sketch that works and the one that doesn’t is that the one that doesn’t expects a voltage to be applied to the VRef pin. That voltage must be at least as high as the voltage that passes through the potentiometer, but not more than 5V.

If you have 0V applied to VRef, then 5V at the pot pin will result in a reading of 1023, as will anything down to 0. Even 0 can, because the process of generating the ratio value to return involves a divide by 0, which produces undefined results.

Thank you, Paul.

The thing is, I don't really understand what you mean :(.

But anyway, i realized what the problem was:

 analogReference(EXTERNAL);

I just "commented" this line of code and I guess all is well now.

I just have to look into it and see why it was there in the first place. ladyada says in the comment that it is put there "If you want to set the aref to something other than 5v". Right now I don't know exactly how exactly I could use this though. I know it is related to what you said. I just don't get it :P

But anyway, i realized what the problem was:

That's what I was trying to tell you. That statement says "Use the voltage applied to the VRef pin as the numerator, when the voltage applied to the analog pin is the numerator" when determining the ratio. If the VRef voltage is 0, the ratio is undefined, because of the divide by 0.

I just don't get it

Suppose that all the voltages to be measured using the analog pins were in the range 0 to 1. With a 5V reference, the range of values returned by analogRead would be 0 to 204.

If, instead, you supplied a constant 1.0V input to VRef, and used that statement, the 1.0 V applied to the analog pin would result in an output of 1023.

So, small changes in the input to the analog pin result in larger differences in the values returned by analogRead.

This is one of the move advanced portable solar power systems that I have seen to date, especially since it has the built in LCD display that displays all the critical data. I would love to design some custom portable solar power solutions around Arduino technology. www.PortableSolarPower.Biz

I gave up trying to read the text at that website as I was continually distracted by the movement of the pictures at the top of the page. Maybe I should change my member name to Grumpy Don.

Don

Hey Paul!

Thank you so much for the advices! Thanks to you, I noticed the presence of the AREF pin. :) and finally understood what it is good for!

All the best, ygreq