Surveillance d'une batterie 18650 avec un ADS1115

Bonjour,
J'explique le projet : je vais, avec un Wemos D1 mini et un capteur d'humidité capacitif surveiller le sol de ma serre ou de tout autre pot.
Relevé une fois toutes 2 heures (et pas la nuit), envoi sur un broker mqtt local qui me préviendra en cas de problème.
Bien entendu, je mets tous les atouts de mon côté pour minimaliser la consommation comme :

  • le régulateur LDO MCP1703T à faible courant de repos ;
  • le mode sleep profond ;
  • le transistor MOSFET AO3401 pour couper l'alimentation du capteur pendant le sleep

Cependant, je voudrais aussi surveiller la batterie.
Or, comme cette carte n'a qu'un seul ADC, je pensais lui adjoindre un ADS1115, alimenté directement par la batterie (4,2v max - et coupé durant le sleep) ce qui est dans sa plage et résoudrait du coup le problème de la tension max appliquée à l'entrée de cet ADC.

Qu'en pensez-vous ?

Merci pour vos constructives réponses.

NB : je n'ai pas l'intention de changer de projet : je garde le Wemos ! :rofl:

J'ai des doutes : un régulateur 250mA ne pourra pas assurer une connexion au WIFI, car celle-ci requiert plus de 400mA en pointe.
Régulateur 500mA impératif :

  • ME6211
  • RT9013
  • etc.

Oui et non.
Un LDO par principe gâche de l'énergie puisqu'il y a une chute de tension à ses bornes.
Typiquement, si on fait du 3V à partir d'un 4V, il y a 25% de perte.
Le LDO permet juste de diminuer le seuil de non régulation de l'alimentation lorsqu'on arrive en fin de charge de la batterie puisqu'il demande moins de tension à ses bornes pour fonctionner.
Si tu veux vraiment minimiser les pertes, il faut regarder du coté des convertisseurs DC/DC. il y en a avec des rendements de l'ordre de 90% et un mode "veille" qui permet de modifier le mode de fonctionnement lorsque le CPU passe en veille.

Il n'est pas évident de trouver des convertisseurs DC/DC consommant très peu.
Le meilleur que je connaisse est le XR2981 (120µA au repos).
Je pense qu'à partir du moment où l'ESP8266 est en veille, il consomme très peu, donc la puissance dissipée dans le régulateur LDO est négligeable.

Renard32 : au passage, si tu regardes le schéma de la D1 MINI, elle est déjà équipée d'un régulateur ME6211, il est totalement inutile d'en ajouter un autre, surtout s'il est moins performant qu'un ME6211.
Solution : alimenter la D1 MINI par sa broche 5V (ou VBUS), directement à partir de la batterie.

Bonjour

+1 pour le ME6211présent sur la WEMOS D1 MIni, sa faible tension de drop out permet de plus à la carte WEMOS D1 Mini de fonctionner en l'alimentant directement avec un accu Li-On sur son entrée "5V" .
On peut exploiter ainsi l'essentiel de la courbe de décharge d'un tel accu (à 3,5V il ne reste pas beaucoup de mAH dans un accu Li-On "3,7V")

J'ai plusieurs cartes D1 MIni qui tournent comme ça sans problème depuis plusieurs années , passant la plupart de leur temps en deepsleep.....(autonomie constatée 6 à 9 mois selon la qualité et la capacité effective des Li-ON au format 18650

pics de courants : en 2015/2016 à la sortie des ESP8266 il a fallu un certain temps pour bien prendre conscience des pics (environ 400mA) du courant absorbé en particulier lors de la connection au point d'accès ou la box..... d'où des resets intempestifs suivis de redémarrages bancals

Bonjour à tous par cette belle matinée.

Même si le moyen de mesure (USB safety tester) n'est pas nécessairement précis, il relève des pointes de 80 mA, 25 à ne rien faire (normal, pas sleep)

ok, ça c'en est une de bonne idée ! et je vois que la plage d'entrée va de 2 à 6 volts.

Bon ce premier point est donc résolu, merci

Même si le moyen de mesure (USB safety tester) n'est pas nécessairement précis, il relève des pointes de 80 mA, 25 à ne rien faire (normal, pas sleep)

Seule une mesure à l'oscilloscope permet de mettre en évidence les pics , trop brefs pour être affichés par un multimetre ou un testeur USB qui par principe font un moyennage sur un intervalle de temps trop long
ce n'est pas une question de précision mais une question de méthode de mesure.

75 ou 80mA correspond au courant moyen avec le WIFI actif, pas aux pointes

Les pics de courants au démarrage et à la connection WiFi sont signalés dans la data sheet de ESP8266 , et confirmés par divers enregistrements effectués avec un oscillo.

Un ESP8266 qui se réveille de deepsleep effectue un redémarrage , il est donc essentiel de lui fournir tout le courant dont il a besoin à ce moment crucial . mes problèmes avec les ESP8266 ont disparu dès lors que j'ai pris en compte ces pics de courant., (régulateur 500mA et condendateurs associés ) sans cela le fonctionnement au redémarrage était aléatoire (ça marchotte jusqu'au moment ou l'ESP8266 se réveille mal ... et vide l'accu sans pour autant réussir sa connection à la box)

Oui, ces régulateurs LDO acceptent en général 5.5V à 6V. Comme une batterie LIPO ou LITHIUM-ION ne va pas au delà de 4.2V à pleine charge, c'est OK.
Par contre ce serait une très mauvaise idée d'alimenter une D1 MINI avec 2 18650 en série.

Ce n'est pas (plus) mon intention. Au pire, 2 en //
d'ailleurs J'en reviens à l'objet principal de ce topic :

Tu n'as guère le choix. La MINI D1 possède une seule entrée ADC.
D'ailleurs deux entrées ADS1115 (16 bits) pourraient être utilisées : capteur + batterie

....je pensais lui adjoindre un ADS1115, alimenté directement par la batterie (4,2v max - et coupé durant le sleep) ce qui est dans sa plage et résoudrait du coup le problème de la tension max appliquée à l'entrée de cet ADC.

pourquoi pas ?

un schéma aiderait à bien saisir toutes les implications éventuelles.

Un détail qui peut parfois rendre service :

Le convertiseur analogique des ESP8266 est par défaut relié à la broche TOUT (entrée analogique unique) mais si en tout début de code on active la ligne

ADC_MODE(ADC_VCC);

la C.A.N se connecte alors intérieurement pour effectuer une mesure de la tension d'alimentation et non la tension présente sur TOUT/ADC

En alternant des réveils avec ou sans cette ligne activée on peut donc acquérir 2 grandeurs analogiques, une externe et une interne.... ça permet au moins une surveillance de la tension d'alimentation à défaut de surveillance de la batterie

Bonjour,

@al1fch, vous précisez dans le post #5

et dans le post #11

ADC_MODE(ADC_VCC);

Si la batterie est connectée directement sur la broche d'alimentation 5V n'est-on pas en mesure de la surveiller ?

Merci
A+

Bonjour @Renard32

Si la batterie est connectée directement sur la broche d'alimentation 5V n'est-on pas en mesure de la surveiller ?

Oui, du moins détecter le moment l'accu est 'presque vide' afin de ne pas entrer en décharge profonde
Donc une surveillance indirecte de l'accu dans la seule partie finale de sa courbe de décharge.

Tant que la tension à ses bornes reste supérieure à 3,5V environ le régulateur de tension linéaire ME6211 délivre 3,3V , que l'accu soit pleinement ou moyennement chargé.

Quant la tension commence à franchir cette valeur, la tension d'alimentation, vaut 3,2V , puis 3,1V....

Perso : si au réveil , avant activation du WiFi, la mesure de tension d'alim interne à l'ESP8266 donne une valeur inférieure à 3,2V je mets l'ESP8266 en veille profonde permanente pour éviter une décharge excessive de l'accu Li-On, me laisser le temps de réagir et le recharger

Bonjour,

Voilà, j'ai donc testé avec la batterie alimentant directement le WEMOS D1 MIni (via son ME6211 intégré). Et donc l'ADS1115 (aussi alimenté par la batterie - pour l'anecdote, la précision est assez époustouflante : au 1/100 de volt !)
Pour tester assez vite, pas de sleep, une LED alimentée directement sur une broche (3,3 volts) et un test toutes les 10 secondes qui envoie la valeur en MQTT sur un broker interne.
Cela se dégrade dès que cela passe sous 3,5 volts.
J'arrêterais donc le circuit dès cette barre passée.

Voilà. Pour moi, cette partie est terminée, merci à toutes et tous pour votre aide.

Par contre j'ai un problème de téléchargement de croquis et mon Wemos est mort.
J'en ai placé un 2ème et toujours le même problème.
J'ai eu l'idée de télécharger hors câblage et cela a fonctionné !...

Si vous pouviez me dire ce qui cloche ? car une fois remis sur le breadboard; il fonctionne comme prévu. (en sachant que je télécharge sans la batterie 18650 branchée !)

Ici, le nouveau croquis de test en test (et donc pas encore validé) :

//#include <SerialESP8266wifi.h>
#include <WiFiClient.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
/*
   Test de la batterie avec ADS1115
   infos intéressantes : https://passionelectronique.fr/tutorial-ads1115/
   Batterie 18650 :
    nominal 3.7v
    Maximal 4.2v
    Minimal 2.75v
    L'expérience montre qu'il vauit mieux arrêter juste en-dessous de 3.5 volts

  L'I2C est géré par la librairie ADS1X15, donc pas de Wire !
*/

#include "ADS1X15.h" //https://github.com/RobTillaart/ADS1X15
ADS1115 ADS(0x48);  // ADS1115 physiquement défini à l'adresse 0x48

/*
  #include <Wire.h>
  const int sclPin = D1;
  const int sdaPin = D2;
*/

const char* nom = "test_ads1115";

#include <ESP8266WiFi.h> // Import ESP8266 WiFi library
#include <PubSubClient.h>// Import PubSubClient library to initialize MQTT protocol

//WIFI
const char* ssid = "sssssss";
const char* password = "pppppp";

//MQTT
const char* mqtt_server = "192.168.0.51";//Adresse IP du Broker Mqtt (pi3-TFA)
const int mqttPort = 1883; //port utilisé par le Broker

WiFiClient espClient;
PubSubClient client(espClient);
char msg[50];

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
// variables pour date et heure
int currentHour =   0;
int currentMinute = 0;
int currentSecond = 0;
int currentDay =    0;
int currentMonth =  0;
int currentYear =   0;
int nbreJoursMois[] = {31, 28, 31, 30, 31, 30, 31, 31, 31, 31, 30, 31};

void setup() {
  Serial.begin(115200);    // open Serial Monitor and set baud rat
  ADS.begin();
  ADS.setGain(0); // ± 6.144 volt (par défaut).
  ADS.setMode(1);  // 0 = CONTINUOUS, 1 = SINGLE (default)
  ADS.setDataRate(0);  // On spécifie la vitesse de mesure de tension qu'on souhaite, allant de 0 à 7 (7 étant le plus rapide, soit 860 échantillons par seconde)
  ADS.readADC(0);      // Et on fait une lecture à vide, pour envoyer tous ces paramètres

  pinMode(D4, OUTPUT);
  digitalWrite(D4, HIGH);

  // Connect to Wi-Fi
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Initialize a NTPClient to get time
  timeClient.begin();
  timeClient.setTimeOffset(3600); // Set offset time in seconds to adjust for your timezone, // GMT +1 = 3600

  // MTTQ
  client.setServer(mqtt_server, 1883);

}

void loop() {
  digitalWrite(D4, LOW); /* éteindre la LED le temps de la mesure
                            jusqu'à la reprise de l'attente.
                            Provoque un léger clignotement */
  // Mesure de la tension
  //int16_t tension = ADS.readADC(0); // Mesure de tension de la broche A0, par rapport à la masse
  int16_t mesure_A0 = ADS.readADC(0);
  float tension = ADS.toVoltage(mesure_A0); /*
                Valeur exprimée en volts dont l’amplitude sera automatiquement
                calculée en fonction du gain préalablement choisi */


  lectureNTP();

  int tg = int(tension);
  int td = int((tension - tg) * 100);

  // préparation message MQTT
  sprintf(msg, "%02d/%02d/%04d %02d:%02d:%02d %s %02d%s%02d",
          currentDay, currentMonth, currentYear, currentHour, currentMinute, currentSecond,
          nom, tg, ".", td  );

  Serial.println(msg);
  reconnect();

  if (tension < 3.5) {
    /* ATTENTION - IMPORTANT
       =====================
       Deep sleep mode :
       the ESP8266 wakes up by itself when GPIO 16 (D0 in NodeMCU board)
       is connected to the RESET pin
       =============================
       L'argument µS est le nombre de micro secondes souhaité avant le réveil.
       Il s'agit d'un entier codé sur 32 bits => donc 2^32 = 4 294 967 296 µs
       = Environ 4294s = environ 71 minutes.
       Cette mise en sommeil ne pourra donc excéder 71 minutes (sauf si  µS = 0)
       Si µS = 0 alors la mise en sommeil durera jusqu'à ce qu'un signal externe
       vienne réveiller le microcontrôleur.
       Il ne pourra pas y avoir de réveil automatique par l'envoi d'un signal de la part de l'horloge RTC.
    */
    sprintf(msg, "%02d/%02d/%04d %02d:%02d:%02d %s %s",
            currentDay, currentMonth, currentYear, currentHour, currentMinute, currentSecond,
            nom, "STOP");

    Serial.println(msg);
    reconnect();
    digitalWrite(D4, LOW);
    ESP.deepSleep(0);
  }

  digitalWrite(D4, HIGH);
  delay(10000);
}


void reconnect() { // #####   MQTT   #####

  // Loop until we're reconnected

  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");

    // Attempt to connect
    if (client.connect(nom)) {
      Serial.println("connected");
      // Once connected, publish an announcement...

      client.publish("SOLS", msg);
      // ... and resubscribe
      //client.subscribe("SOLS");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void lectureNTP() {
  timeClient.update();
  time_t epochTime = timeClient.getEpochTime();
  //Get a time structure
  struct tm *ptm = gmtime ((time_t *)&epochTime);
  currentHour = timeClient.getHours();
  currentMinute = timeClient.getMinutes();
  currentSecond = timeClient.getSeconds();
  currentDay = ptm->tm_mday;
  currentMonth = ptm->tm_mon + 1;
  currentYear = ptm->tm_year + 1900;


  /*
     H E U R E   D ' É T É   /   H I V E R

     D'après https://forums.futura-sciences.com/mathematiques-superieur/36243-passage-heure-dete-heure-hiver.html

  */
  int jourEte;
  int heureEte;
  int jourHiver;
  int heureHiver;
  int maintenant;
  int ecartHeure = 0;
  if (currentYear % 4 == 0 )
    // Le dernier dimanche de mars --- last sunday of march
    jourEte =  (31 - (5 * currentYear / 4 + 4) % 7);
  heureEte = 30000 + (jourEte * 100) + 2 ; //  mmjjhh
  // Le dernier dimanche d'octobre --- last sunday of october
  jourHiver = (31 - (5 *  currentYear / 4 + 1) % 7);
  heureHiver = 100000 + (jourHiver * 100) + 2;// mmjjhh
  maintenant = currentMonth * 10000 + currentDay * 100 + currentHour;// mmjjhh
  if (maintenant >= heureEte && maintenant < heureHiver) {
    ecartHeure = 1; // DST europe = gmt 2 (summer time) + 1 hour
  }
  else
  {
    ecartHeure = 0;
  }

  // Ajustement heure -> jour -> mois
  // L'heure d'été n'affecte pas février (bissextile) et s'arrête en octobre
  currentHour += ecartHeure;
  if (currentHour == 24) {
    currentHour = 0;
    currentDay += 1;
  }
  if (currentDay > nbreJoursMois[currentMonth - 1]) {
    currentDay = 1;
    currentMonth += 1;
  }

}

Peut-être la liaison RST D0 ?

Sur certaines de mes cartes D1 Mini, pas toutes, la liaison filaire entre D0 et RST empêche le flashage.
Pour ces cartes je relie D0 et RST avec une résistance de 100 Ohm.

Le reveil d'un deep-sleep et le flashage sont alors OK tous les deux

Merci, je vais essayer cela (plus tard)

J'ai pas vraiment fini : quand je regarde le datasheet de l'ADS1115 mon mauvais anglais semble dire qu'il consomme 150 µA en mode continu, mais qu'il est "auto Shut-Down" en mode "Single-Shot".
Comme je ne fais pas de mesure continue (c'est un tout autre process), il devrait se mettre à l'arrêt automatiquement après la mesure ?
Ai-je bien compris ?

Vrai, mais cela ne te dispensera pas de vérifier la consommation de ton montage final, avec un multimètre. C'est plus sûr.