KOLANKY - Chargeur voiture électrique connecté 6A-16A Tuya à moins de 90€

Il est possible d’utiliser un ESP8266 mais dans ce cas, pas de WIFI, ce qui limite l’intérêt de la chose. Ceci car le seul GPIO analogique de ce composant sert aussi en interne pour mesurer le signal WIFI.
Par contre, et c’est ce que j’avais fait au début, on peut en mettre 2. J’avais empilé 2 WEMOS mini v3, une pour gérer la borne, l’autre pour le WIFI, les 2 étant reliées par liaison série. J’ai testé, cela fonctionne, mais j’ai préféré mettre un ESP32…

Pour les fonctions manquantes :
WIFI et MQTT il y a plein d’exemples partout, vous pouvez trouver tout seuls…

MesureTension:

// Mesure la tension de la ligne CP par l'entrée analogique

void MesureTension() {
  char s[20];
  TensionLigneCP = 0;
  float Somme = 0;
  static unsigned long Tempo;

  for (int i = 1; i < 11; i++) {  // suite à parasites, on fait la moyenne de plusieurs mesures
    Tempo = millis();

    do {
      brut = analogRead(CP);
      if (TensionLigneCP < brut) TensionLigneCP = brut;  // mesure la tension max du PWM
    } while ((millis() - Tempo) < 4);                    // pendant une durée max de 4 ms (cycle de 1 ms)

    Somme = Somme + TensionLigneCP;
  }

  TensionLigneCP = Somme / 10;

  TensionLigneCP = TensionLigneCP * CoeffTension;
  

  snprintf(s, sizeof(s), "Tension CP: %.1f V", TensionLigneCP);
  PrintScreen(Lig2, Col1, s);  // envoie la tension de la ligne sur l'écran
  //publie(TopicControl, TensionLigneCP, 1);                               // pour debug
}

Lit Pzem : si vous n’avez pas de PZEM, vous pouvez ne pas utiliser cette fonction :

void LitPZEM() {
  char s [20];

  // lit les données du capteur
  Volt = pzem.voltage();
  Ampere = pzem.current();
  Puiss = pzem.power();
  kWh = pzem.energy();
  float Freq = pzem.frequency();
  CosPhi = pzem.pf();

  // vérifie la validité des données
  if (isnan(Volt)) {
    //Serial.println("Erreur tension");
    Volt = 0;
  }
  if (isnan(Ampere)) {
    //Serial.println("Erreur courant");
    Ampere = 0;
  }
  if (isnan(Puiss)) {
    //Serial.println("Erreur puissance");
  }
  if (isnan(kWh)) {
    //Serial.println("Erreur energie");
  }
  if (isnan(Freq)) {
    //Serial.println("Erreur frequence");
  }
  if (isnan(CosPhi)) {
    //Serial.println("Erreurg CosPhi");
  }

  snprintf(s, sizeof(s), "%.0fV %.0fA %.1fkWh ", Volt, Ampere, kWh);
  PrintScreen(Lig3, Col1, s);
  
}

arrêt de la charge:

void ArretCharge() {
  // si la tension de la ligne CP change, on arrete la charge
  //
  char s[20];
  static unsigned long Tempo;

  EnvoiRapport(1);  // arrete le PWM
  while (Ampere > .9) {
    LitPZEM();
    PrintScreen(Lig1, Col1, "Attente Amp < 1");
    delay(1000);  // attend que le courant soit faible pour éviter un arc aux bornes du relais
  }
  ArretRelais();
  EnCharge = false;
  
  if (Statut != "Pas de 12V !") {    // Pour ne pas changer le statut par "charge stoppée" si pas de 12 Volts
    PrintScreen(Lig1, Col1, "Charge stoppée");
    Statut = "Charge stoppée";
    if (MQTTclient.connected()) MQTTclient.publish(TopicStatut, "Charge stoppée");
  }

  Tempo = millis();
  if (!DemandeArret) {  // si on n'a pas reçu de demande d'arret
    do {                // délai avant de recoller le relais pour réautoriser la charge
      snprintf(s, sizeof(s), "Charge dans %.0d s", 15 - ((millis() - Tempo) / 1000));
      PrintScreen(Lig4, Col1, s);
      
      delay(1000);
    } while ((millis() - Tempo) < 15000);
    PrintScreen(Lig4, Col1, "Reprise");
  } else PrintScreen(Lig4, Col1, "Enlever le câble");
}

gestion relais : celle la, vous auriez pu la trouver tout seul aussi, mais bon :

void MarcheRelais() {
  if (!EtatRelais){
    delay(2000);
    digitalWrite(RelaisPin, HIGH);
    EtatRelais = true;
    //Serial.println("Marche Relais ");
    PrintScreen(Lig4, Col1, "Relais HT On");
  }
}

//***********************************

void ArretRelais() {
  if (EtatRelais == true){
    digitalWrite(RelaisPin, LOW);
    EtatRelais = false;
    //Serial.println("Arrêt relais ");
    PrintScreen(Lig4, Col1, "Relais HT Off");
  }
}

Pour ceux qui ont un écran :

void PrintScreen (int Lig, int Col, String Message) {
  
  //u8g2.clearBuffer();               //efface le buffer
  
  u8g2.setFont(u8g2_font_7x13B_tf);   // choix d'une police de caractère
  u8g2.setCursor(Col, Lig);           // position du début du texte (colonne, ligne)
  u8g2.setDrawColor(0);               // efface la ligne
  u8g2.drawBox(Col,Lig-10,128,12);    // en traçant un rectangle noir
  //u8g2.sendBuffer();                // l'image qu'on vient de construire est affichée à l'écran
  //delay(1000);
  u8g2.setDrawColor(1);               // remet l'écriture en blanc
  u8g2.setCursor(Col, Lig);           // position du début du texte (colonne, ligne)
  u8g2.print(Message);                // écriture de texte
  u8g2.sendBuffer();                  // l'image qu'on vient de construire est affichée à l'écran

  //delay(100);

}

A bientôt…

Grand merci @jeunegeo pour les précisions
N’aitant pas un spécialiste j’espère pouvoir m’en sortir avec ces compléments.
Je vous tiens au jus bien sûr

Merci aussi, mon esp32 arrive demain, je m’y met de suite.
Pour le wifi en effet y a plein d’exemple. Pour mqtt c’est un peu plus compliqué car c’est en lien avec ha (avoir les bon topic pour récup les infos et envoyer les bonnes commandes,.mais quand on en sera là on aura bien avancé.)
Bizarre ton info sur esp8266 car j’en ai un sous esphome avec mesure de tension donc avec utilisation de l’entrée analogique.

Tu peux mesurer avec un ESp8266, et avoir le Wifi, mais pas les 2 en même temps. Si ta mesure est rapide, cela fonctionne. Mais pour la borne, il faut mesurer la tension sur CP en permanence, car la voiture peut la modifier à tout moment.
On pourrait essayer de ne la mesurer que pendant 100 ms toutes les secondes, ou un truc comme ça, à tester ! Mais il y a un risque de déconnexion du Wifi… :face_with_head_bandage:

Content de voir que certains sont intéressés !

il vous faut aussi cette fonction :

void EnvoiRapport(float RappCycl) {
  // configure la sortie avec le rapport demandé
  //le rapport de sortie se configure de 0 à 1023, donc :

  RappCycl = 1023 * RappCycl;

  ledcWrite(PWMCanal, 1023 - RappCycl);  // 1023-RappCycl si sortie inversée (ce qui est le cas ici)
  //analogWrite(PwmOutput, RappCycl);             // si sortie pas inversée
  if (RappCycl == 1023) {  // si PWM = 1023 alors le PWM est arreté
    PWM = false;
  } else PWM = true;
}

Si pb avec le Wifi ou le Mqtt, je les mettrai aussi, mais c’est en codant qu’on progresse!
Si besoin d’autres, demandez! Je ne suis pas toujours disponible, donc soyez patients! :grinning:

une p’tite dernière pour la route :

void EmissionMQTT() {

  //char s [20];

  //snprintf(s, sizeof(s), "tension:%.0f, amp:%.0f, energy:%.1f ", Volt, Ampere, kWh);
  // MQTTclient.publish(TopicStatut, s);

  publie(TopicTension, Volt, 1);
  publie(TopicCourant, Ampere, 1);
  publie(TopicPuissance, Puiss, 0);
  publie(TopicEnergie, kWh, 2);
  publie(TopicCosPhi,CosPhi,2);

  publie(TopicAmp, Amp, 2);

  //publie(TopicControl, TensionLigneCP, 1);

  // transforme la chaine "Statut" en Char array pour la publier
  // fonctionne, mais la methode avec des IF en dessous est plus facile...
  /*
  int LongStat = Statut.length() + 1; 
  char TabStat[LongStat];
  Statut.toCharArray(TabStat, LongStat); 
  MQTTclient.publish(TopicStatut, TabStat);
  */
  if (WiFi.status() == WL_CONNECTED) {
    if (Statut == "VE connecté") MQTTclient.publish(TopicStatut, "VE connecté");
    if (Statut == "Chargeur prêt") MQTTclient.publish(TopicStatut, "Chargeur prêt");
    if (Statut == "en charge") MQTTclient.publish(TopicStatut, "VE en charge");
    if (Statut == "Pas de 12V !") MQTTclient.publish(TopicStatut, "Pas de 12V !");
  }
}

//********************************************************
//transforme la valeur en Float, puis en String, puis en Char Array et publie
void publie(const char *Topic, float ValR, int NbDec) {

  String ValeurP = String(ValR, NbDec);                  // NbDec est le nombre de décimales prises en compte
  //Serial.print(ValeurP); Serial.print("  pour  "); Serial.println(Topic);
  char PourPublier[ValeurP.length() + 1];
  ValeurP.toCharArray(PourPublier, ValeurP.length() + 1);
  if (MQTTclient.connect("clientId")) {
    MQTTclient.publish(Topic, PourPublier);
  }

}  // fin de publie

1 « J'aime »

Je doit avoir un ESP32 qui traine
Je vais le tester

On peut très bien utiliser l’entrée analogique d’un ESP8266 et utiliser le wifi en même temps (je l’ai fait sans problème pour un autre projet qui n’a rien à voir) mais on ne peut pas utiliser le « rapide » (je sais plus comment ils appellent ça)
Il faut faire une mesure « de temps en temps » (1 à chaque bouclage principal du Main par exemple) et ça va très bien.

Merci pour ces précisions que je ne connaissais pas.

Oui, et c’est bien ce que j’indique dans mon message

Encore une fonction utile, c’est la réception MQTT, en interruption.
Les parties Surplus ou ConsoRouteur sont à adapter ou à supprimer en fonction de votre config, car j’ai un routeur qui m’envoie l’info de conso ou d’injection de la maison, et c’est cela qui sert à ajuster le courant de charge.
Mais pas utile dans un premier temps.

// Callback pour réception par MQTT (une commande)

void ReceptionMQTT(char* topic, byte* payload, unsigned int length) {

  //Serial.println("réception MQTT");
  //MQTTclient.publish(TopicControl, "réception MQTT");

  if (strcmp(topic, TopicCommande) == 0) {
    if (payload[0] == 'I') {
      String Texte = "";
      for (int i = 1; i < length; i++) {
        Texte = Texte + (char)payload[i];
      }
      GestionSurplusAuto = false;      // si on reçoit une commande I, on passe en gestion manuelle du surplus.
      Amp = Texte.toFloat();           // tranforme la chaine en float
      if (Amp < AmpMin) Amp = AmpMin;  // pour ne pas dépasser les limites fixées
      if (Amp > AmpMax) Amp = AmpMax;  //
      Rapp = Amp / .6 / 100;           // rapport entre l'intensité et le rapport cyclique du PWM
      EnvoiRapport(Rapp);              //
      ModifRapp = millis();            // init tempo pour inhiber controle depassement courant
      NbAjust = 0;                     // remise à zéro du nombre d'ajustement du courant possible
      MQTTclient.publish(TopicControl, "Réglage I");
    }

    if (payload[0] == 'A') {           // arrêt charge
      DemandeArret = true;
      ArretCharge();
    }

    if (payload[0] == 'G') {           // Bascule entre gestion auto et manuelle pour le surplus
      if (!GestionSurplusAuto) {
        GestionSurplusAuto = true;
        MQTTclient.publish(TopicControl, "Gestion Auto vraie");
      } else {
        GestionSurplusAuto = false;
        MQTTclient.publish(TopicControl, "Arret Gestion Auto");
      }
    }

    if (payload[0] == 'R') {            // demande de reprise de charge
      DemandeArret = false;
    }

    if (payload[0] == 'Z') {            // Remise à zéro kWh PZEM
      pzem.resetEnergy();
      MQTTclient.publish(TopicControl, "Reset kWh BorneVE");
      //ArretCharge();
    }
    //ProdJour = Texte.toInt();
  }

  if (strcmp(topic, TopicSurplus) == 0) {  //  reçoit le temps entre 2 pulses du surplus en millisecondes
    String Texte = "";
    for (int i = 0; i < length; i++) {
      Texte = Texte + (char)payload[i];
    }
    long Temps = Texte.toInt();  // tranforme la chaine en long
    Surplus = 3600000 / Temps;   // division euclidienne, tranforme le temps en Watts
    SurplusRecu = true;
    CompteurSurplus = millis();  // sert à calculer le temps écoulé depuis la dernière réception de surplus, dans GestionSurplus
  }

  if (strcmp(topic, TopicConsoRout) == 0) {  //  reçoit la conso mesurée par le routeur (si negatif on consomme, positif on exporte)
    String Texte = "";
    for (int i = 0; i < length; i++) {
      Texte = Texte + (char)payload[i];
    }
    long Temps = Texte.toInt();  // tranforme la chaine en long
    ConsoRout = Temps;   // division euclidienne, tranforme le temps en Watts
    ConsoRecu = true;
  }
}

Pour le 12 V : il faut qu’il soit bien régulé. Sur certaines alim, à vide on a plus que 12 V et un peu moins en charge. Donc attention aux alim trop simples, telle que celle du lien cité au dessus par @Legeantbleu , le 12 V ne doit pas être bien régulé.
Dans ce type d’alim, souvent il n’y a que le 5V de régulé… Et 100 mA pour le 5V c’est limite : un ESP c’est 70 mA en pointe et il faut ajouter la conso du relai.

Actuellement, je n’ai plus qu’une alim 12 V, pas de 5V car ma carte ESP-C3 peut être alimentée par du 12V (ou du 220V) et elle fabrique l’alim pour l’ESP (3,3 V).

Pour le transistor, j’ai mis ce que j’avais (2N2222A) mais vous pouvez mettre tout transistor NPN compatible ou avec un courant admissible plus grand.

Et attention à la commande du relai, il faut soit une carte relai qui accepte une commande en 3,3 V, soit ajouter un transistor entre le GPIO et le relai, soit avoir un relai en 3,3 V.

Salut @jeunegeo
Encore merci pour ces infos qui seront précieuses.
J’ai retrouvé un ESP 32 WROOM 32 de AZ Delivery mais il a une alimentation en 5V donc il faut que je prévois en conséquence.
Sinon tu as un lien pour ta carte alimentée en 12v ?

J’ai trouvé une carte interessante :
image

C’est l’esp c3 celui là, moins cher ici

Relai intégré et entrée 12v, pas mal je ne connaissais pas :slight_smile:

Reste plus qu’à trouver une bonne alimentation 12 v !

C’est la carte que j’utilise en ce moment, mais je ne me sers pas de la partie 220 V. Pour simplifier, il faudrait la même sans la partie 220 V;

J’ai modifié la sortie Wifi pour mettre une antenne externe, car ma borne est un peu trop loin de ma box.

la même un poil moins cher :
https://fr.aliexpress.com/item/1005006046192283.html?spm=a2g0o.cart.0.0.5c91378dayDJpt&mp=1&gatewayAdapt=glo2fra

sinon, celle la à l’air bien :
https://fr.aliexpress.com/item/1005005599324679.html?spm=a2g0o.cart.0.0.5ccd378d6fSmoO&mp=1&gatewayAdapt=glo2fra

La même avec un connecteur d’antenne ça serait top!

Merci @jeunegeo
Je viens de commander la seconde avec livraison prévue le 8 juillet.
Un conseil pour l’alimentation 12 v ?

Est-ce que tu pourrais indiquer quel chargeur chinois tu as utilisé pour ça, et où se trouve la sortie PWM ?

Ce serait une super solution pas très cher : un chargeur chinois, un ESP dessus, et zou on a une wallbox.