État de charge d'une batterie sur Arduino

Bonjour à tous,

Me voilà confronter à un problème de taille...

En effet, j'ai construit un arduino NANO sur batterie qui lorsqu'il est branché en USB, Recharge la batterie, et lorsque que l'usb es débranché, décharge la batterie pour alimenter l'arduino NANO (Un petit régulateur de charge un TP4056 es bien sur entre la batterie et l'arduino)

Seulement voilà, j'aimerai mesurer la charge de cette batterie afin d'en afficher l'état sur un petit écran OLED 128x64, mais voila ... lorsque je mesure la tension en entrée de A0, j'obtiens tout le temps 1023 lorsque mon Arduino es sur batterie et des chiffres qui semblent corrects lorsqu'il est branché en USB.

Je ne comprend pas. J'ai essayer de prendre la tension depuis la sortie 5v du TP4056, et de la batterie directement mais rien à faire..

La batterie es une LiPo de 3000mAh de 3,7v

le convertisseur es un TP4056

et mon arduino es un NANO ATMEGA328P

et mon code :

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);

void setup() {

  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32
  display.display();
  delay(1000);
  display.clearDisplay();
 
}




void loop() {

  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.0);
  Serial.println(voltage);
  display.setTextSize(4);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.print(voltage);
  display.display();
  display.clearDisplay();

  
}

À votre écoute !

Merci !!

It should be so. According to the datasheet ADC = Vin * 1024 / Vref.
Arduino by default sets its Vref = Vcc, so if Vref = Vbat you always get the maximum ADC value 1023.
If you want to measure the battery voltage, there are two ways:

  1. You are using external Vref
  2. You are using internal Vref = 1.1V.

You can read more detailed here How to know VCC voltage in arduino ?

1 Like

Un morceau de code qui fait ça

/* getBattery
    Measure battery level
    
    Change ADC's ref to Vcc and read internal bandgap reference value
    Compute battery level
    Switch back ADC's ref to internal
    Note: internalRef shall be multiplied by 1023
    
    input:
            nothing
    output:
            uint32_t : battery level in mV
*/
uint32_t getBattery(void){
    uint32_t result;
    // Read 1.1V reference against AVcc
    uint8_t sav_reg = ADMUX;
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
    delay(5); // Wait for Vref to settle
    ADCSRA |= _BV(ADSC); // Convert
    while (bit_is_set(ADCSRA,ADSC));
    result = ADCL;
    result |= ADCH<<8;
    result = internalRef / result; // Back-calculate AVcc in mV
    ADMUX = sav_reg;              // restore previous ADC configuration
    return result;
}

internalRef est une variable globale qui contient la valeur de la référence interne en mV.
Cette valeur doit être déterminée soit par la mesure, soit empiriquement.
Pour la déterminer par la mesure il faut faire un petit morceau de code qui va sélectionner la référence interne et on mesure précisément la tension sur la broche AREF du microprocesseur.
La détermination empirique va consister à mesurer la tension de la batterie et faire le calcul inverse pour en déduire la valeur d'internalRef.

1 Like

Thanks for the idea with saving and restoring ADMUX.