Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Digression sur le code UxIx3 et les reboot / ENFIN PLUS DE PLANTAGE
#1
J'ai de nouveau analysé le code UxIx3, qui pose problème depuis l'adoption de la bibliothèque "cartes" V3.01 et suivantes au lieu de feu la V2.17 qui marchait parfaitement.

Le problème tourne en partie autour du WIFI (mais pas uniquement je pense) et semble avoir été résolu pour ceux qui ont peu d'ESP32, ou n'utilisent pas le module UxIx3 (tri-phasé).

Le code UxIx3 tel qu'il est écrit actuellement consomme inutilement des ressources, et il n'est pas impossible qu'il y ait depuis la V3.01 des interactions entre les deux cores, possiblement avec les "mutex hardware" ou autres.

Actuellement, le code UxIx3 envoie une requête de données au module JSY-MK-333, puis lit la réponse caractère par caractère jusqu'à les avoir tous lus. C'est une perte de temps inutile, car, en supposant que le module réponde 'dans l'instant', cela prend au minimum  141 données x 10 bits / 9600 = 150 ms.

J'ai donc simplement "dissocié" la requête de la lecture, pour être sûr que lorsque le core viendra lire la réponse, tout le message sera déjà dans le buffer et sera donc lu "à grande vitesse". J'aurais pu aussi venir vérifier si toutes les données avaient été reçues, avec un timeout, avant de les lire toutes, mais sans bloquer.

Le code actuel marche simplement parce que le serial.read() est en partie "bloquant", c'est à dire qu'il attend avec un timeout, dont j'ai lu qu'il était par défaut de 1 seconde. C'est curieux quand on veut faire du temps réel d'avoir des read avec timeout. Mais c'est comme çà.

Pour résoudre le problème, j'ai simplement sorti la requête elle-même de la "lecture", et lancé une première requête à la fin de l'init du port série (voir plus loin).

Et j'ai modifié le code principal en lisant, puis en relançant une requête, sachant que je ne viendrai lire la réponse que 800ms plus tard (lors de l'extinction du timer), donc en étant sûr qu'elle sera dans le buffer de réception dans son intégralité.

if (Source == "UxIx3") {
          Lecture_JSY333();
          PeriodeProgMillis = 800;
          Request_data_JSY333();
        }


Sans doute parce que dans le code V3.0x il y a de nouvelles inter-actions 'parasites' entre le temps réel des deux cores, le simple fait d'utiliser moins longtemps l'UART libère de la ressource qui améliore grandement les choses (pour le WIFI ?? j'en doute).

Très curieux, mais c'est comme ça. Donc je prends puique ainsi cela tombe en marche.

La prochaine étape sera pour moi de passer la comm série à 19200 comme cela a été si bien fait par un autre d'entre nous, pour gagner un facteur 2 sur la vitesse de transmission et réduire encore le temps de lecture et d'occupation de l'UART. Et je testerai en continu le buffer de réception pour ne pas en retarder la lecture comme je le fais actuellement ( comme c'est très bien fait pour le Linky).

En tout cas, je n'ai plus de plantage de mon serveur UxIx3, ce qui est déjà très bien.


// *************************************************
// * Client lecture JSY-MK-333 * Triphasé          *
// * Développement initial de Pierre F (Mars 2024) *
// * update PhDV61 Juin 2024 et Août 2024          *
// *************************************************

void Setup_JSY333() {
  MySerial.setRxBufferSize(SER_BUF_SIZE);
  MySerial.begin(9600, SERIAL_8N1, RXD2, TXD2);  //PORT DE CONNEXION AVEC LE CAPTEUR JSY-MK-333
  delay(10);
  Request_data_JSY333();
}

void Request_data_JSY333() {
int i;
  byte msg_send[] = { 0x01, 0x03, 0x01, 0x00, 0x00, 0x44, 0x44, 0x05 };
  for (i = 0; i < 8; i++) {
    MySerial.write(msg_send[i]);
  }
}  


void Lecture_JSY333() {

  float Tension_M1, Tension_M2, Tension_M3;
  float Intensite_M1, Intensite_M2, Intensite_M3;
  float PVA_M_inst1, PVA_M_inst2, PVA_M_inst3;
  float PW_inst1, PW_inst2, PW_inst3;
  byte Lecture333[200];
  bool injection;
  bool sens1, sens2, sens3;
  long delta_temps = 0;
  int a = 0;


  while (MySerial.available()) {
    Lecture333[a] = MySerial.read();
    a++;
  }
...


Voilà.

Edit : je viens de lire que les tâches WIFI tournaient par défaut (arrrrghhh) sur ... le core 0. Ceci expliquant peut-être cela...
V12.03 modifiée. 1 serveur UxIx3, 1 Linky, 1 client Triac CE tampon + 1 client SSR CE tampon + 1 client SSR sur CE tri + 2 SSR sur radiateurs bain d'huile d'appoint. Variateurs de fréquence Piscine.
8 panneaux (4 SO 2 S, 2 SE ) 425Wc sur 4 HM800 produisent 13kWh par jour ensoleillé à fin Novembre.
Répondre
#2
Bien, je viens de modifier le code à nouveau pour venir tester la quantité de data reçue (avec timeout d'une seconde) et m'assurer que le message a été entièrement reçu avant d'en faire la lecture. Je teste toutes les 150ms (temps de transmission), mais on pourrait le faire plus rapidement. La lecture effective est ultra rapide car le message est arrivé et "bufferisé". C'est donc une affaire de quelques centaines de micro-secondes.

Et devinez quoi ?
Même avec mes trois ESP clients avec une page web données brutes, ET mon serveur avec une page web données brutes ne créent aucune erreur pour ce que j'ai pu constater. C'est un IMMENSE progrès. Cela veut bien dire qu'il y a des interactions entre la fonction "lecture" du core zéro et les fonctions WIFI.

Voilà le code à modifier :

code principal :

Partie "init" :
...
//Port Série si besoin
if (pSerial > 0) {
RXD2 = RXD2_2;
TXD2 = TXD2_2;
if (pSerial == 1) {
RXD2 = RXD2_1;
TXD2 = TXD2_1;
}
if (Source == "UxIx2") {
Setup_UxIx2();
}
if (Source == "UxIx3") {
Setup_JSY333();
}
...

Partie "boucle principale"

...
//Recupération des données RMS
//******************************
if (tps - LastRMS_Millis > PeriodeProgMillis) { //Attention delicat pour eviter pb overflow
LastRMS_Millis = tps;
unsigned long ralenti = long(PuissanceS_M / 10); // On peut ralentir échange sur Wifi si grosse puissance en cours

if (Source == "UxI") {
LectureUxI();
PeriodeProgMillis = 40;
}
if (pSerial > 0) {
if (Source == "UxIx2") {
LectureUxIx2();
PeriodeProgMillis = 400;
}
if (Source == "UxIx3") {
if (Message_recu() )
{
Lecture_JSY333();
Request_data_JSY333();
}
PeriodeProgMillis = 150;
}
...


code UxIx3 entier :

// *************************************************
// * Client lecture JSY-MK-333 * Triphasé *
// * Développement initial de Pierre F (Mars 2024) *
// * update PhDV61 Juin 2024 et Août 2024 *
// *************************************************

long timeout_lecture = 0;

void Setup_JSY333() {
MySerial.setRxBufferSize(SER_BUF_SIZE);
MySerial.begin(9600, SERIAL_8N1, RXD2, TXD2); //PORT DE CONNEXION AVEC LE CAPTEUR JSY-MK-333
delay(10);
Request_data_JSY333();
}

void Request_data_JSY333() {
int i;
byte msg_send[] = { 0x01, 0x03, 0x01, 0x00, 0x00, 0x44, 0x44, 0x05 };
for (i = 0; i < 8; i++) {
MySerial.write(msg_send[i]);
}
timeout_lecture = millis()+1000; // pas plus de 1s max pour obtenir les données dans le buffer de réception
}

bool Message_recu() {
if ( MySerial.available() == 141) // les données sont là !
return true;
else if ( millis() > timeout_lecture ) // il y a eu un problème!
{ MySerial.flush();
StockMessage("timeout lecture module JSY-MK-333 - nb de données reçues : " + String(MySerial.available()) );
Request_data_JSY333();
return false;
}
return false;
}

void Lecture_JSY333() {
float Tension_M1, Tension_M2, Tension_M3;
float Intensite_M1, Intensite_M2, Intensite_M3;
float PVA_M_inst1, PVA_M_inst2, PVA_M_inst3;
float PW_inst1, PW_inst2, PW_inst3;

byte Lecture333[200];
bool injection;
bool sens1, sens2, sens3;
long delta_temps = 0;

int a = 0;
while (MySerial.available()) {
Lecture333[a] = MySerial.read();
a++;
}

if (a == 141) { // message reçu complet
delta_temps = (unsigned long)(millis() - Temps_precedent); // temps écoulé depuis le dernier appel
Temps_precedent = millis(); // on conserve la valeur du temps actuel pour le calcul précédent

Tension_M1 = ((float)(Lecture333[ 3] * 256 + Lecture333[ 4])) / 100;
Tension_M2 = ((float)(Lecture333[ 5] * 256 + Lecture333[ 6])) / 100;
Tension_M3 = ((float)(Lecture333[ 7] * 256 + Lecture333[ 8])) / 100;
Intensite_M1 = ((float)(Lecture333[ 9] * 256 + Lecture333[10])) / 100;
Intensite_M2 = ((float)(Lecture333[11] * 256 + Lecture333[12])) / 100;
Intensite_M3 = ((float)(Lecture333[13] * 256 + Lecture333[14])) / 100;

sens1 = (Lecture333[104]) & 0x01;
sens2 = (Lecture333[104] >> 1) & 0x01;
sens3 = (Lecture333[104] >> 2) & 0x01;

if (sens1) { Intensite_M1 *= -1; }
if (sens2) { Intensite_M2 *= -1; }
if (sens3) { Intensite_M3 *= -1; }

injection = (Lecture333[104] >> 3) & 0x01; //si sens est true, injection

// Lecture des Puissances actives de chacune des phases
PW_inst1 = (float)(Lecture333[15] * 256.0) + (float)Lecture333[16];
PW_inst2 = (float)(Lecture333[17] * 256.0) + (float)Lecture333[18];
PW_inst3 = (float)(Lecture333[19] * 256.0) + (float)Lecture333[20];

//Lecture des puissances apparentes de chacune des phases, qu'on signe comme le Linky
PVA_M_inst1 = (float)(Lecture333[35] * 256) + (float)Lecture333[36];
if (sens1) { PVA_M_inst1 = -PVA_M_inst1; }
PVA_M_inst2 = (float)(Lecture333[37] * 256) + (float)Lecture333[38];
if (sens2) { PVA_M_inst2 = -PVA_M_inst2; }
PVA_M_inst3 = (float)(Lecture333[39] * 256) + (float)Lecture333[40];
if (sens3) { PVA_M_inst3 = -PVA_M_inst3; }

if (injection) {
PuissanceS_M_inst = 0;
PuissanceI_M_inst = ((float)((float)(Lecture333[21] * 16777216) + (float)(Lecture333[22] * 65536) + (float)(Lecture333[23] * 256) + (float)Lecture333[24]));
PVAS_M_inst = 0;
PVAI_M_inst = abs(PVA_M_inst1 + PVA_M_inst2 + PVA_M_inst3); // car la somme des puissances apparentes "signées" est négative puisqu'en "injection" au global

// PhDV61 : on considère que cette puissance active "globale" a duré "delta_temps", et on l'intègre donc pour obtenir une énergie en Wh
Energie_jour_Injectee += ((float)delta_temps / 1000) * (PuissanceI_M_inst / 3600.0);

} else { // soutirage
PuissanceI_M_inst = 0;
PuissanceS_M_inst = ((float)((float)(Lecture333[21] * 16777216) + (float)(Lecture333[22] * 65536) + (float)(Lecture333[23] * 256) + (float)Lecture333[24]));
PVAI_M_inst = 0;
PVAS_M_inst = PVA_M_inst1 + PVA_M_inst2 + PVA_M_inst3;

// PhDV61 : on considère que cette puissance active "globale" a duré "delta_temps", et on l'intègre donc pour obtenir pour obtenir une énergie en Wh
Energie_jour_Soutiree += ((float)delta_temps / 1000) * (PuissanceS_M_inst / 3600.0);
}

// PowerFactor_M = ((float)(Lecture333[53] * 256 + Lecture333[54])) / 1000; ce facteur de puissance ne veut rien dire en tri-phasé en cas d'injection sur au moins une phase

Energie_M_Soutiree = ((float)((float)(Lecture333[119] * 16777216) + (float)(Lecture333[120] * 65536) + (float)(Lecture333[121] * 256) + (float)Lecture333[122])) * 10;
Energie_M_Injectee = ((float)((float)(Lecture333[135] * 16777216) + (float)(Lecture333[136] * 65536) + (float)(Lecture333[137] * 256) + (float)Lecture333[138])) * 10;

MK333_dataBrute = "<strong>Triphasé</strong><br>Phase1 : " + String(int(Tension_M1)) + "V " + String(Intensite_M1) + "A</br>";
MK333_dataBrute += "<br>Phase2 : " + String(int(Tension_M2)) + "V " + String(Intensite_M2) + "A</br>";
MK333_dataBrute += "<br>Phase3 : " + String(int(Tension_M3)) + "V " + String(Intensite_M3) + "A</br>";
MK333_dataBrute += "<br>Puissance active soutirée : " + String(PuissanceS_M_inst) + "W</br>";
MK333_dataBrute += "<br>Puissance active injectée : " + String(PuissanceI_M_inst) + "W</br>";
MK333_dataBrute += "<br>Puissance apparente soutirée : " + String(PVAS_M_inst) + "VA</br>";
MK333_dataBrute += "<br>Puissance apparente injectée : " + String(PVAI_M_inst) + "VA</br>";

MK333_dataBrute += "<br>Puissance apparente phase1 : " + String(PVA_M_inst1) + "VA</br>";
MK333_dataBrute += "<br>Puissance apparente phase2 : " + String(PVA_M_inst2) + "VA</br>";
MK333_dataBrute += "<br>Puissance apparente phase3 : " + String(PVA_M_inst3) + "VA</br>";

if (PVA_M_inst1 != 0)
MK333_dataBrute += "<br>Facteur de puissance phase 1 : " + String(abs(PW_inst1 / PVA_M_inst1)) + "</br>";
if (PVA_M_inst2 != 0)
MK333_dataBrute += "<br>Facteur de puissance phase 2 : " + String(abs(PW_inst2 / PVA_M_inst2)) + "</br>";
if (PVA_M_inst3 != 0)
MK333_dataBrute += "<br>Facteur de puissance phase 3 : " + String(abs(PW_inst3 / PVA_M_inst3)) + "</br>";

MK333_dataBrute += "<br>Energie jour nette soutirée (Linky): " + String(Energie_jour_Soutiree) + "Wh</br>";
MK333_dataBrute += "<br>Energie jour nette injectée (Linky): " + String(Energie_jour_Injectee) + "Wh</br>";

MK333_dataBrute += "<br>Energie totale soutirée : " + String(Energie_M_Soutiree) + "Wh</br>";
MK333_dataBrute += "<br>Energie totale injectée : " + String(Energie_M_Injectee) + "Wh</br>";

Pva_valide = true;
filtre_puissance();
PuissanceRecue=true; //Reset du Watchdog à chaque trame du JSY reçue
EnergieActiveValide = true;
if (cptLEDyellow > 30) {
cptLEDyellow = 4;
}
} else {
StockMessage("Pas tout reçu, pas traité... nombre de données : " + String(a));
}
}

Il me reste à faire tourner quelques jours maintenant en l'état, pour m'assurer que les problèmes sont derrière moi définitivement.
V12.03 modifiée. 1 serveur UxIx3, 1 Linky, 1 client Triac CE tampon + 1 client SSR CE tampon + 1 client SSR sur CE tri + 2 SSR sur radiateurs bain d'huile d'appoint. Variateurs de fréquence Piscine.
8 panneaux (4 SO 2 S, 2 SE ) 425Wc sur 4 HM800 produisent 13kWh par jour ensoleillé à fin Novembre.
Répondre
#3
(16-08-2024, 09:18 PM)PhDV61 a écrit : Bien, je viens de modifier le code à nouveau pour venir tester la quantité de data reçue (avec timeout d'une seconde) et m'assurer que le message a été entièrement reçu avant d'en faire la lecture. Je teste toutes les 150ms (temps de transmission), mais on pourrait le faire plus rapidement. La lecture effective est ultra rapide car le message est arrivé et "bufferisé". C'est donc une affaire que quelque centaines de micro-secondes.

Et devinez quoi ?
Même avec mes trois ESP clients avec une page web données brutes, ET mon serveur avec une page web données brutes ne créent aucune erreur pour ce que j'ai pu constater. C'est un IMMENSE progrès. Cela veut bien dire qu'il y a des interactions entre la fonction "lecture" du core zéro et les fonctions WIFI.

Voilà le code à modifier :

code principal :

Partie "init" :
...
//Port Série si besoin
  if (pSerial > 0) {
    RXD2 = RXD2_2;
    TXD2 = TXD2_2;
    if (pSerial == 1) {
      RXD2 = RXD2_1;
      TXD2 = TXD2_1;
    }
    if (Source == "UxIx2") {
      Setup_UxIx2();
    }
    if (Source == "UxIx3") {
      Setup_JSY333();
    }
...

Partie "boucle principale"

...
//Recupération des données RMS
    //******************************
    if (tps - LastRMS_Millis > PeriodeProgMillis) {  //Attention delicat pour eviter pb overflow
      LastRMS_Millis = tps;
      unsigned long ralenti = long(PuissanceS_M / 10);  // On peut ralentir échange sur Wifi si grosse puissance en cours

      if (Source == "UxI") {
        LectureUxI();
        PeriodeProgMillis = 40;
      }
      if (pSerial > 0) {
        if (Source == "UxIx2") {
          LectureUxIx2();
          PeriodeProgMillis = 400;
        }
        if (Source == "UxIx3") {
          if (Message_recu() )
          {
            Lecture_JSY333();
            Request_data_JSY333();
          }
            PeriodeProgMillis = 150;
        }
...


code UxIx3 entier :

// *************************************************
// * Client lecture JSY-MK-333 * Triphasé          *
// * Développement initial de Pierre F (Mars 2024) *
// * update PhDV61 Juin 2024 et Août 2024          *
// *************************************************

long timeout_lecture = 0;

void Setup_JSY333() {
  MySerial.setRxBufferSize(SER_BUF_SIZE);
  MySerial.begin(9600, SERIAL_8N1, RXD2, TXD2);  //PORT DE CONNEXION AVEC LE CAPTEUR JSY-MK-333
  delay(10);
  Request_data_JSY333();
}

void Request_data_JSY333() {
int i;
  byte msg_send[] = { 0x01, 0x03, 0x01, 0x00, 0x00, 0x44, 0x44, 0x05 };
  for (i = 0; i < 8; i++) {
    MySerial.write(msg_send[i]);
  }
  timeout_lecture = millis()+1000; // pas plus de 1s max pour obtenir les données dans le buffer de réception


bool Message_recu() {
if ( MySerial.available() == 141)      // les données sont là  !
  return true;                 
else if ( millis() > timeout_lecture )  // il y a eu un problème!
  { MySerial.flush();
    StockMessage("timeout lecture module JSY-MK-333 - nb de données reçues : " + String(MySerial.available()) );
    Request_data_JSY333();
    return false;
  }
return false; 
}

void Lecture_JSY333() {
  float Tension_M1, Tension_M2, Tension_M3;
  float Intensite_M1, Intensite_M2, Intensite_M3;
  float PVA_M_inst1, PVA_M_inst2, PVA_M_inst3;
  float PW_inst1, PW_inst2, PW_inst3;

  byte Lecture333[200];
  bool injection;
  bool sens1, sens2, sens3;
  long delta_temps = 0;

  int a = 0;
  while (MySerial.available()) {
    Lecture333[a] = MySerial.read();
    a++;
  }

  if (a == 141) {                                              // message reçu complet
    delta_temps = (unsigned long)(millis() - Temps_precedent);  // temps écoulé depuis le dernier appel
    Temps_precedent = millis();                                // on conserve la valeur du temps actuel pour le calcul précédent

    Tension_M1 =  ((float)(Lecture333[ 3] * 256 + Lecture333[ 4])) / 100;
    Tension_M2 =  ((float)(Lecture333[ 5] * 256 + Lecture333[ 6])) / 100;
    Tension_M3 =  ((float)(Lecture333[ 7] * 256 + Lecture333[ 8])) / 100;
    Intensite_M1 = ((float)(Lecture333[ 9] * 256 + Lecture333[10])) / 100;
    Intensite_M2 = ((float)(Lecture333[11] * 256 + Lecture333[12])) / 100;
    Intensite_M3 = ((float)(Lecture333[13] * 256 + Lecture333[14])) / 100;

    sens1 = (Lecture333[104])      & 0x01;
    sens2 = (Lecture333[104] >> 1) & 0x01;
    sens3 = (Lecture333[104] >> 2) & 0x01;

    if (sens1) { Intensite_M1 *= -1; }
    if (sens2) { Intensite_M2 *= -1; }
    if (sens3) { Intensite_M3 *= -1; }

    injection = (Lecture333[104] >> 3) & 0x01;  //si sens est true, injection

    // Lecture des Puissances actives de chacune des phases
    PW_inst1 = (float)(Lecture333[15] * 256.0) + (float)Lecture333[16];
    PW_inst2 = (float)(Lecture333[17] * 256.0) + (float)Lecture333[18];
    PW_inst3 = (float)(Lecture333[19] * 256.0) + (float)Lecture333[20];

    //Lecture des puissances apparentes de chacune des phases, qu'on signe comme le Linky
    PVA_M_inst1 = (float)(Lecture333[35] * 256) + (float)Lecture333[36];
    if (sens1) { PVA_M_inst1 = -PVA_M_inst1; }
    PVA_M_inst2 = (float)(Lecture333[37] * 256) + (float)Lecture333[38];
    if (sens2) { PVA_M_inst2 = -PVA_M_inst2; }
    PVA_M_inst3 = (float)(Lecture333[39] * 256) + (float)Lecture333[40];
    if (sens3) { PVA_M_inst3 = -PVA_M_inst3; }

    if (injection) {
      PuissanceS_M_inst = 0;
      PuissanceI_M_inst = ((float)((float)(Lecture333[21] * 16777216) + (float)(Lecture333[22] * 65536) + (float)(Lecture333[23] * 256) + (float)Lecture333[24]));
      PVAS_M_inst = 0;
      PVAI_M_inst = abs(PVA_M_inst1 + PVA_M_inst2 + PVA_M_inst3);  // car la somme des puissances apparentes "signées" est négative puisqu'en "injection" au global

      // PhDV61 : on considère que cette puissance active "globale" a duré "delta_temps", et on l'intègre donc pour obtenir une énergie en Wh
      Energie_jour_Injectee += ((float)delta_temps / 1000) * (PuissanceI_M_inst / 3600.0);

    } else {  // soutirage
      PuissanceI_M_inst = 0;
      PuissanceS_M_inst = ((float)((float)(Lecture333[21] * 16777216) + (float)(Lecture333[22] * 65536) + (float)(Lecture333[23] * 256) + (float)Lecture333[24]));
      PVAI_M_inst = 0;
      PVAS_M_inst = PVA_M_inst1 + PVA_M_inst2 + PVA_M_inst3;

      // PhDV61 : on considère que cette puissance active "globale" a duré "delta_temps", et on l'intègre donc pour obtenir pour obtenir une énergie en Wh
      Energie_jour_Soutiree += ((float)delta_temps / 1000) * (PuissanceS_M_inst / 3600.0);
    }

    // PowerFactor_M = ((float)(Lecture333[53] * 256 + Lecture333[54])) / 1000; ce facteur de puissance ne veut rien dire en tri-phasé en cas d'injection sur au moins une phase

    Energie_M_Soutiree = ((float)((float)(Lecture333[119] * 16777216) + (float)(Lecture333[120] * 65536) + (float)(Lecture333[121] * 256) + (float)Lecture333[122])) * 10;
    Energie_M_Injectee = ((float)((float)(Lecture333[135] * 16777216) + (float)(Lecture333[136] * 65536) + (float)(Lecture333[137] * 256) + (float)Lecture333[138])) * 10;

    MK333_dataBrute = "<strong>Triphasé</strong><br>Phase1 : " + String(int(Tension_M1)) + "V " + String(Intensite_M1) + "A</br>";
    MK333_dataBrute += "<br>Phase2 : " + String(int(Tension_M2)) + "V " + String(Intensite_M2) + "A</br>";
    MK333_dataBrute += "<br>Phase3 : " + String(int(Tension_M3)) + "V " + String(Intensite_M3) + "A</br>";
    MK333_dataBrute += "<br>Puissance active soutirée : " + String(PuissanceS_M_inst) + "W</br>";
    MK333_dataBrute += "<br>Puissance active injectée : " + String(PuissanceI_M_inst) + "W</br>";
    MK333_dataBrute += "<br>Puissance apparente soutirée : " + String(PVAS_M_inst) + "VA</br>";
    MK333_dataBrute += "<br>Puissance apparente injectée : " + String(PVAI_M_inst) + "VA</br>";

    MK333_dataBrute += "<br>Puissance apparente phase1  : " + String(PVA_M_inst1) + "VA</br>";
    MK333_dataBrute += "<br>Puissance apparente phase2  : " + String(PVA_M_inst2) + "VA</br>";
    MK333_dataBrute += "<br>Puissance apparente phase3  : " + String(PVA_M_inst3) + "VA</br>";

    if (PVA_M_inst1 != 0)
      MK333_dataBrute += "<br>Facteur de puissance phase 1 : " + String(abs(PW_inst1 / PVA_M_inst1)) + "</br>";
    if (PVA_M_inst2 != 0)
      MK333_dataBrute += "<br>Facteur de puissance phase 2 : " + String(abs(PW_inst2 / PVA_M_inst2)) + "</br>";
    if (PVA_M_inst3 != 0)
      MK333_dataBrute += "<br>Facteur de puissance phase 3 : " + String(abs(PW_inst3 / PVA_M_inst3)) + "</br>";

    MK333_dataBrute += "<br>Energie jour nette soutirée (Linky): " + String(Energie_jour_Soutiree) + "Wh</br>";
    MK333_dataBrute += "<br>Energie jour nette injectée (Linky): " + String(Energie_jour_Injectee) + "Wh</br>";

    MK333_dataBrute += "<br>Energie totale soutirée : " + String(Energie_M_Soutiree) + "Wh</br>";
    MK333_dataBrute += "<br>Energie totale injectée : " + String(Energie_M_Injectee) + "Wh</br>";

    Pva_valide = true;
    filtre_puissance();
    PuissanceRecue=true;  //Reset du Watchdog à chaque trame du JSY reçue
    EnergieActiveValide = true;
    if (cptLEDyellow > 30) {
      cptLEDyellow = 4;
    }
  } else {
    StockMessage("Pas tout reçu, pas traité... nombre de données : " + String(a));
  }
}

Il me reste à faire tourner quelques jours maintenant en l'état, pour m'assurer que les problèmes sont derrière moi définitivement.

que de bonnes nouvelles à vs lire, youpi!!!!

Merci en tout cas.
ESP32 (v12.05): 1 Source UxIx3, 3 routeurs avec 1 SSR sur le CE (ESP Externe) dont 2 avec Sonde température, 1 routeur avec 2 SSRs: Pompe Piscine et PAC
16 panneaux 445WC avec Enphase 7 tri-phasé avec une idée d'extension de qqs PVs plug&play sur le pool house sous HomeAssistant 
Répondre
#4
Petite information supplémentaire pour ceux qui ont un serveur UxIx3 :
J'ai instrumenté le code pour mesurer la récurrence à laquelle on peut solliciter une mesure du module, dès lors qu'on dissocie la requête de données de sa lecture :

Le module a fini de répondre à toute requête et d'envoyer TOUTES ces données entre 200 et 400ms après avoir été interrogé (300ms en moyenne sur une longue durée), même avec une demande de 141 data, et à 9600 bauds. C''est ce que j'obtiens en venant vérifier à récurrence de 50ms si les données sont toutes arrivées ou pas encore, et en mesurant le temps entre deux messages reçus.

Et je n'ai plus de message d'erreur de connexion chez les clients lors de l'utilisation des pages web en ayant augmenté à 800ms la récurrence d'interrogation. C'est vraisemblablement lié au fait que la tâche de lecture ne perd plus un temps fou à lire en attendant l'arrivée effective de chaque donnée.

Je vais maintenant essayer de retourner à une interrogation du serveur de données toutes les 400ms par ses clients.
V12.03 modifiée. 1 serveur UxIx3, 1 Linky, 1 client Triac CE tampon + 1 client SSR CE tampon + 1 client SSR sur CE tri + 2 SSR sur radiateurs bain d'huile d'appoint. Variateurs de fréquence Piscine.
8 panneaux (4 SO 2 S, 2 SE ) 425Wc sur 4 HM800 produisent 13kWh par jour ensoleillé à fin Novembre.
Répondre
#5
Bizarre ton affaire, le code uxix3 est le même que celui du uxix2, lui même inspiré de tout ce qu'on trouve de similaire pour d'autres projets.
D'autres personnes que toi sont elles victimes de ces plantages?

As tu testé ma méthode : passage du module en 19200 et code optimisé partie calcul et nombre de données reçues?
Répondre
#6
Lis bien ce que j'ai écrit au dessus concernant le wifi, les interactions, et l'occupation de l'UART.
La dernière bibliothèque carte V3.0x a introduit pas mal de soucis de timing sur le wifi, les priorités... etc, et n'est pas au niveau de la 2.017.

Je n'ai plus de plantage avec cette méthode "propre" (ie asynchrone ne s'appuyant pas sur les timeout du serial.read() ) d'interrogation du module.

Je lis des réponses complètes - 141 data à 9600 bits/s à une récurrence entre 200ms et 400ms en attendant que toutes les data soient reçues dans le buffer de réception avant de déclencher leur lecture.

Maintenant que tout tourne parfaitement sans planter, même,avec de multiples pages web, je vais passer à 19200.
V12.03 modifiée. 1 serveur UxIx3, 1 Linky, 1 client Triac CE tampon + 1 client SSR CE tampon + 1 client SSR sur CE tri + 2 SSR sur radiateurs bain d'huile d'appoint. Variateurs de fréquence Piscine.
8 panneaux (4 SO 2 S, 2 SE ) 425Wc sur 4 HM800 produisent 13kWh par jour ensoleillé à fin Novembre.
Répondre
#7
Si cela donne lieu à une nouvelle version officielle, je conseille d'ajouter Energie_M_Soutiree = Energie_jour_Soutiree (idem injectée) ce qui permet d'afficher, et de remonter en mqtt, la donnée "linky" de conso/injection, sans avoir à modifier le reste du code (on pert certes la valeur cumulée mais dans tous les cas elle est fausse...)
Répondre
#8
j'ai installé la v12 et regarde ton code Smile
mais je ne comprends pas tout
l'idée est de lancer la requete puis d'attendre periodepromillis avant de lire la réponse
mais quand on regarde le code :

void Lecture_JSY333() {
float Tension_M1, Tension_M2, Tension_M3;
float Intensite_M1, Intensite_M2, Intensite_M3;
float PVA_M_inst1, PVA_M_inst2, PVA_M_inst3;
float PW_inst1, PW_inst2, PW_inst3;

byte Lecture333[200];
bool injection;
bool sens1, sens2, sens3;
long delta_temps = 0;

Requete_JSY333();

int a = 0;
while (MySerial.available()) {
Lecture333[a] = MySerial.read();
a++;
}


on n'attend pas entre la requête et la lecture des infos
donc je ne vois pas trop ce qui a changé ?
Répondre
#9
il y a une modif dans le code principal pour initialiser la première requête.

Ainsi, lorsqu'on vient lire la première fois au bous de "périodemillis" qui vaut 1000, les données sont prêtes dans le buffer de réception, et on les lit en quelques dizaines de ms, sans bloquer, et sans attendre.

...
/* **********************
* ****************** *
* * Tâches Coeur 0 * *
* ****************** *
**********************
*/

void Task_LectureRMS(void *pvParameters) {
if (Source == "UxIx3") {
Setup_JSY333(); // init port série
delay(100); // pour s'assurer que l'init du port série est ok coté module
PeriodeProgMillis = 1000; // la première lecture aura lieu 1000ms plus tard
Requete_JSY333(); // requête initiale au module. La première lecture aura lieu PeriodeProgMillis =1000ms plus tard.
// et les données seront déjà toutes dans le buffer de réception
}
for (;Wink {
unsigned long tps = millis();


et ensuite, on vient lire toutes les secondes :
...
if (Source == "UxIx3") {
Lecture_JSY333();
PeriodeProgMillis = 1000;
}

... qui commence par envoyer une nouvelle demande de données pour que la fois suivante, elles soient de nouveau déjà dans le buffer de réception.

void Lecture_JSY333() {
float Tension_M1, Tension_M2, Tension_M3;
float Intensite_M1, Intensite_M2, Intensite_M3;
float PVA_M_inst1, PVA_M_inst2, PVA_M_inst3;
float PW_inst1, PW_inst2, PW_inst3;

byte Lecture333[200];
bool injection;
bool sens1, sens2, sens3;
long delta_temps = 0;

Requete_JSY333(); // <-----------------------
V12.03 modifiée. 1 serveur UxIx3, 1 Linky, 1 client Triac CE tampon + 1 client SSR CE tampon + 1 client SSR sur CE tri + 2 SSR sur radiateurs bain d'huile d'appoint. Variateurs de fréquence Piscine.
8 panneaux (4 SO 2 S, 2 SE ) 425Wc sur 4 HM800 produisent 13kWh par jour ensoleillé à fin Novembre.
Répondre
#10
Je ne comprends pas, dans le code de uxix3.ino on lance la requête puis sans attendre on lit les données, sans attendre. Je dois mal comprendre quelque chose ?

Requete_JSY333();

int a = 0;
while (MySerial.available()) {
Lecture333[a] = MySerial.read();
a++;
}


Où est l'attente de 1000ms ?
Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 4 visiteur(s)