A class to Measure the Battery
-
Hi all, for the sake of beginners like myself and to get advice on it, here is the code i have done to measure the battery of my sensors
based on @sundberg84 here: EasyNewbie-PCB-for-MySensors and articles i've read here
Please provide advice on how to manage switching analogReference()
Here is the class definition:
class MyBM { public: MyBM(); MyBM(const float _VMIN, const float _VMAX); void setup(void); void MeasureBattery(void); //The battery calculations private: void burnreadings(void); float VBAT_PER_BITS; float VMIN; // Vmin (radio Min Volt)=1.9V (564v) float VMAX; // Vmax = (2xAA bat)=3.0V (892v) int batteryPcnt = 0; // Calc value for battery % int batLoop = 0; // Loop to help calc average int batArray[3]; // Array to store value for average calc. unsigned int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point int sValue; float Vbat; };You can change the values in the constructor MyBM() ; by default it is the resistors 1M and 470k for EasyPCB.
Following advice found on stackoverflow, i make 8 readings in burnreadings() when switching from analogReference(INTERNAL) to analogReference(DEFAULT) back & forth
MyBM::MyBM() { this->VMIN= 2.0 ; // Vmin (radio Min Volt)=1.9V (564v) this->VMAX= 3.3; // Vmax = (2xAA bat)=3.0V (892v) this->VBAT_PER_BITS= (1470/470)*(1.1/1024); } MyBM::MyBM(const float _VMIN, const float _VMAX) { MyBM(); this->VMIN= _VMIN; this->VMAX= _VMAX; } void MyBM::burnreadings(void) { for (int i = 0; i < 8; i++) { analogRead(BATTERY_SENSE_PIN); } } void MyBM::setup(void) { //========================= // BATTERY MEASURER //DEFAULT: the default analog reference of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards) //INTERNAL: an built-in reference, equal to 1.1 volts on the ATmega168 or ATmega328 and 2.56 volts on the ATmega8 (not available on the Arduino Mega) //EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference. analogReference(INTERNAL); // set the ADC reference to 1.1V burnreadings(); // make 8 readings but don't use them delay(10); // idle some time //Battery inital calc DPR("With Battery VMax (100%) = "); DPR(VMAX); DPR("volts and Vmin (0%) = "); DPR(VMIN); DPRLN(" volts"); DPR("Battery Percent 25%/50%/75% calculates to: "); DPR(((VMAX - VMIN) / 4) + VMIN); DPR("/"); DPR(((VMAX - VMIN) / 2) + VMIN); DPR("/"); DPRLN(VMAX - ((VMAX - VMIN) / 4)); sValue = analogRead(BATTERY_SENSE_PIN); DPR("Batterysens :"); DPRLN(sValue); Vbat = sValue * VBAT_PER_BITS; batteryPcnt = static_cast<int>(((Vbat - VMIN) / (VMAX - VMIN)) * 100.); DPR("Current battery are measured to (please confirm!): "); DPR(batteryPcnt); DPR(" % - Or "); DPRLN(Vbat); DPRLN(" Volts"); analogReference(DEFAULT); // set the ADC reference back to internal burnreadings(); // make 8 readings but don't use them delay(10); // idle again //========================= } void MyBM::MeasureBattery() { analogReference(INTERNAL); // set the ADC reference to 1.1V burnreadings(); // make 8 readings but don't use them delay(10); // idle some time // Battery monitoring reading sValue = analogRead(BATTERY_SENSE_PIN); DPR("Batterysens :"); DPRLN(sValue); //delay(500); // Calculate the battery in % Vbat = sValue * VBAT_PER_BITS; batteryPcnt = static_cast<int>(((Vbat - VMIN) / (VMAX - VMIN)) * 100.); DPR("Battery percent: "); DPR(batteryPcnt); DPR(" %"); DPR("Battery Voltage: "); DPR(Vbat); DPRLN(" Volts"); // Add it to array so we get an average of 3 (3x20min) batArray[batLoop] = batteryPcnt; if (batLoop > 2) { batteryPcnt = (batArray[0] + batArray[1] + batArray[2]); batteryPcnt = batteryPcnt / 3; if (batteryPcnt > 100) { batteryPcnt = 100; } DPR("Battery Average (Send): "); DPR(batteryPcnt); DPRLN(" %"); sendBatteryLevel(batteryPcnt); batLoop = 0; } else { batLoop++; } analogReference(DEFAULT); // set the ADC reference back to internal burnreadings(); // make 8 readings but don't use them delay(10); // idle again }Here is how i use it with a sensor that manages both interrupts and a sensor-specific timeout
// sdj is an object representing the sensor MyBM bm; void setup() { sdj.setup(); bm.setup(); } void loop() { if (tripped==0) { the_switch= sdj.get(); } else if (tripped==MY_WAKE_UP_BY_TIMER) { if (sdj.wait_next()) { // timeout needs to do something for the sensor sdj.resetCode(); } else { // timeout , nothing occured for sensor bm.MeasureBattery(); } } // Sleep until something happens with the sensor or timeout tripped= sdj.sleep(WAIT_LOOP); }
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login