I'm trying to get this code working but I'm having strange value for "u_mV"
I guess, it's because I'm making division but even if I declare FLOAT, the result is also unwanted value.
It goes high, low, even negative for no apparent reason.
Here is the piece of code I'm suspecting to be wrong :
int calcul_tension_batterie_mV () { //tout déclaré en int car les valeurs manipulées < 65536
const int R1_kOhm = 217 ; //resistance du pont diviseur en kOhm
const int R2_kOhm = 100 ; //resistance du pont diviseur en kOhm
int Vcc = readVcc();
int UPONT = analogRead (UPont);
//unsigned int result = (UPONT) * Vcc /1024 * (R1_kOhm + R2_kOhm)/R2_kOhm * 1000;
int result = (UPONT) * Vcc * 3;
return result; // UBat en millivolts
}
Here is the entire code :
#define DEBUG
#define Led13 13
#define UPont A0 //meusure de tension au pont diviseur
#define Relai1 7
#define Pompe Relai1
#define PompeOn digitalWrite (Pompe, 0)
#define PompeOff digitalWrite (Pompe, 1)
#define EtatPompe !digitalRead (Pompe)
#define Relai2 6
#define Frigo Relai2
#define FrigoOn digitalWrite (Frigo, 0)
#define FrigoOff digitalWrite (Frigo, 1)
#define EtatFrigo !digitalRead(Pompe)
#define Relai3 5
#define Onduleur Relai3
#define OnduleurOn digitalWrite (Onduleur, 0)
#define OnduleurOff digitalWrite (Onduleur, 1)
#define EtatOnduleur !digitalRead(Onduleur)
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0) ;
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1121280L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 (Ref 1.1V = 1.095V)
return result; // Vcc in millivolts
}
int calcul_tension_batterie_mV () { //tout déclaré en int car les valeurs manipulées < 65536
const int R1_kOhm = 217 ; //resistance du pont diviseur en kOhm
const int R2_kOhm = 100 ; //resistance du pont diviseur en kOhm
int Vcc = readVcc();
int UPONT = analogRead (UPont);
//unsigned int result = (UPONT) * Vcc /1024 * (R1_kOhm + R2_kOhm)/R2_kOhm * 1000;
int result = (UPONT) * Vcc * 3;
return result; // UBat en millivolts
}
void blinkL13()
{
digitalWrite(Led13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(Led13, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}
void AllumeFrigo()
{
PompeOff;
if (~EtatOnduleur)
{
OnduleurOn;
delay(2000);
}
FrigoOn;
//delay(10000);
}
void EteintFrigo()
{
FrigoOff;
if (~EtatPompe)
{
delay(500);
OnduleurOff;
}
}
void AllumePompe()
{
if (~EtatOnduleur)
{
OnduleurOn;
delay(1000);
}
PompeOn;
delay(5000);
}
void EteintPompe()
{
PompeOff;
if (~EtatFrigo)
{
delay(500);
OnduleurOff;
}
}
void setup() {
#ifdef DEBUG
Serial.begin(9600);
#endif
pinMode (Pompe, 1);
pinMode (Frigo, 1);
pinMode (Onduleur, 1);
pinMode (UPont, 0);
PORTD |= (1<<Onduleur) | (1<<Pompe) | (1<<Frigo); //Relais ouverts a 1 (fonctionnement des appareil à l'arrêt pour 1)
}
void loop() {
long u_mV = calcul_tension_batterie_mV ();
#ifdef DEBUG
int Vcc = readVcc();
int UPONT = (analogRead (UPont)) * readVcc() /1024;
Serial.print("Vcc = ");
Serial.print(Vcc);
Serial.print(" UPONT = ");
Serial.print(UPONT);
Serial.print(" u_mV = ");
Serial.print(u_mV);
Serial.print(" Onduleur = ");
Serial.print(EtatOnduleur);
Serial.print(" Frigo = ");
Serial.print(EtatFrigo);
Serial.print(" Pompe = ");
Serial.println(EtatPompe);
#endif
blinkL13();
if (u_mV > 12600)
{
AllumeFrigo();
}
if (u_mV < 12000)
{
EteintFrigo();
}
if (u_mV > 14400)
{
AllumePompe();
}
if (u_mV < 12600)
{
EteintPompe();
}
}
No way, even with FLOAT, it gives me even negative value !
Here is the suspicious piece of code modified :
float calcul_tension_batterie_mV () { //tout déclaré en int car les valeurs manipulées < 65536
const int R1_kOhm = 217 ; //resistance du pont diviseur en kOhm
const int R2_kOhm = 100 ; //resistance du pont diviseur en kOhm
int Vcc = readVcc();
int UPONT = analogRead (UPont);
float result = (UPONT) * Vcc /1024 * (R1_kOhm + R2_kOhm)/R2_kOhm * 1000;
//int result = (UPONT) * Vcc * 3;
return result; // UBat en millivolts
}
Here the complete code.
#define DEBUG
#define Led13 13
#define UPont A0 //meusure de tension au pont diviseur
#define Relai1 2
#define Pompe Relai1
#define PompeOn digitalWrite (Pompe, 0)
#define PompeOff digitalWrite (Pompe, 1)
#define EtatPompe !digitalRead (Pompe)
#define Relai2 3
#define Frigo Relai2
#define FrigoOn digitalWrite (Frigo, 0)
#define FrigoOff digitalWrite (Frigo, 1)
#define EtatFrigo !digitalRead(Pompe)
#define Relai3 4
#define Onduleur Relai3
#define OnduleurOn digitalWrite (Onduleur, 0)
#define OnduleurOff digitalWrite (Onduleur, 1)
#define EtatOnduleur !digitalRead(Onduleur)
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0) ;
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1121280L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 (Ref 1.1V = 1.095V)
return result; // Vcc in millivolts
}
float calcul_tension_batterie_mV () { //tout déclaré en int car les valeurs manipulées < 65536
const int R1_kOhm = 217 ; //resistance du pont diviseur en kOhm
const int R2_kOhm = 100 ; //resistance du pont diviseur en kOhm
int Vcc = readVcc();
int UPONT = analogRead (UPont);
float result = (UPONT) * Vcc /1024 * (R1_kOhm + R2_kOhm)/R2_kOhm * 1000;
//int result = (UPONT) * Vcc * 3;
return result; // UBat en millivolts
}
void blinkL13()
{
digitalWrite(Led13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(Led13, LOW); // turn the LED off by making the voltage LOW
delay(1000);
}
void AllumeFrigo()
{
PompeOff;
if (~EtatOnduleur)
{
OnduleurOn;
delay(2000);
}
FrigoOn;
//delay(10000);
}
void EteintFrigo()
{
FrigoOff;
if (~EtatPompe)
{
delay(500);
OnduleurOff;
}
}
void AllumePompe()
{
if (~EtatOnduleur)
{
OnduleurOn;
delay(1000);
}
PompeOn;
delay(5000);
}
void EteintPompe()
{
PompeOff;
if (~EtatFrigo)
{
delay(500);
OnduleurOff;
}
}
void setup() {
#ifdef DEBUG
Serial.begin(9600);
#endif
pinMode (Pompe, 1);
pinMode (Frigo, 1);
pinMode (Onduleur, 1);
pinMode (UPont, 0);
PORTD |= (1<<Onduleur) | (1<<Pompe) | (1<<Frigo); //Relais ouverts a 1 (fonctionnement des appareil à l'arrêt pour 1)
}
void loop() {
float u_mV = calcul_tension_batterie_mV ();
#ifdef DEBUG
int Vcc = readVcc();
int UPONT = (analogRead (UPont)) * readVcc() /1024;
Serial.print("Vcc = ");
Serial.print(Vcc);
Serial.print(" UPONT = ");
Serial.print(UPONT);
Serial.print(" u_mV = ");
Serial.print(u_mV);
Serial.print(" Onduleur = ");
Serial.print(EtatOnduleur);
Serial.print(" Frigo = ");
Serial.print(EtatFrigo);
Serial.print(" Pompe = ");
Serial.println(EtatPompe);
#endif
blinkL13();
if (u_mV > 12600)
{
AllumeFrigo();
}
if (u_mV < 12000)
{
EteintFrigo();
}
if (u_mV > 14400)
{
AllumePompe();
}
if (u_mV < 12600)
{
EteintPompe();
}
}
Sounds like you're overflowing during integer calculations. Try switching your int variables to longs.
int Vcc = readVcc();
int UPONT = analogRead (UPont);
float result = (UPONT) * Vcc
Vcc is in millivolts, we can expect that value to be in the thousands range. UPONT will be 0 to 1023, which means the first calculation could easily be in the millions., well beyond the range of an int.
Just to let you know I've done this to get "u_mV" :
const int R1_kOhm = 217 ; //resistance du pont diviseur en kOhm
const int R2_kOhm = 86 ; //resistance du pont diviseur en kOhm 86
long Vcc = readVcc();
int UPONT = analogRead (A0);
float tension_de_pont = UPONT * Vcc /1024;
float u_mV = tension_de_pont * (R1_kOhm + R2_kOhm)/R2_kOhm;
I don't really understand the reason it didn't work and the reason it now works !
Indeed, it seems to have something to do with double and float but I got it working only making some tries, not understanding what I was doing !
Your original code started by multiplying two ints:
int Vcc = readVcc();
float result = (UPONT) * Vcc
Your updated code multiplies an int and a long:
long Vcc = readVcc();
float tension_de_pont = UPONT * Vcc
The intermediate result (after the first multiplication) is treated as the larger of the two types. In the original code, it was trying to store UPONT * Vcc in an int. Considering your values of 5050 and 3457, the result is too big to store in an int, which can only store a number up to 32,767. In the newer code, the intermediate result is stored in a long, which has a maximum value 2,147,483,647. That is plenty large enough to store 5050 * 3467.