Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Optimisation partie UXIX3
#11
Je prends une mesure toutes les 400ms,.les messaages sont complets et les fonnees varient... Le doc du jsy est truffé d'erreur. Tu n'arrives pas a descendre sous les 1000ms car tu es en 9600 et tu lis l'ensemble des trames je pense

Je vais essayer ta méthode.
En routage, ma puissance active oscille entre +20 et -20 a peu près. Même si l'intégrale est fausse ca fera au max 450wh d'injection ce qui est pas si mal comparé aux valeurs du jsy...

Copie d'écran qui montre la réactivité avec mesures toutes les 400ms:


Pièces jointes Miniature(s)
   
Répondre
#12
(15-06-2024, 12:42 PM)piamp a écrit : Je ne suis pas expert des communications série d'où les talonnements...
Je ne comprends pas trop comment cela fonctionne, je pense que l'on reste dans la boucle while tant que des données arrivent, mais n'en suis pas sûr...

Dans la dernière version de mon code, on reçoit 101 octets soit 404 bits.
a 19200 bps, cela fait 20ms pour recevoir la totalité du message, si je ne me trompe pas ?

Moi non plus, mais j'ai bricolé pas mal sur Arduino et les ports série.

Et non, malheureusement, cela ne fonctionne pas comme cela.
Je pense en fait que c'est par 'hasard' (ou miracle ?) que ça marche plus ou moins en l'état.
Rien n'est "bloquant dans ces échanges totalement asynchrones, et quelques lignes de code tournent bien plus vite sur l'ESP32 que 'arrivée d'un nouvel octet chaque 1ms.

Et dans tous les cas, la doc indique que les données ne sont pas rafraichies à plus de 1s.

Ce que j'ai fait pour le moment pour sécuriser, c'est
> ajouter un simple timer d'attente des données (une seconde)
> lancer une requête initiale à la fin de l'init_UxIx3 et armer le timer d'attente de lecture à 1 seconde.
> lire les données toutes les secondes, et à la fin de la lecture, envoyer une nouvelle requête et ré-armer le timer d'attente.

Avec ce principe, on doit je pense lire correctement un message toutes les secondes.

A moins de 1s, j'obtiens des messages incomplets une fois sur 2.
cdlt,
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
#13
Il y a déjà un timer dans le .ino principal, regle a 600ms par defaut

je teste votre code
Les nouvelles données calculées ne sont pas celles qui remontent en MQTT à priori ?
Répondre
#14
J'ai modifié MQTT.ino pour faire remonter ces valeurs
je verrai demain si c'est cohérent avec les exports linky !
Répondre
#15
(15-06-2024, 04:46 PM)piamp a écrit : Il y a déjà un timer dans le .ino principal, regle a 600ms par defaut

je teste votre code
Les nouvelles données calculées ne sont pas celles qui remontent en MQTT à priori ?

non, les nouvelles données calculées apparaissent seulement dans la page "données brutes" à ce stade.
Les données qui apparaissent sur la page "main" comptabilisent le total injecté, et le total soutiré par jour, et depuis le démarrage du module.

J'essaie de suivre les évolutions d'André, mais lorsqu'on développe d'autres choses dans son coin, cela devient de plus en plus dur, car il faut sans cesse recoller à la "baseline".

Je vous invite à vous connecter sur votre serveur UxIx3 et à vérifier que lorsque vous interrogez à 600ms, vous avez bien des réponses valides et complètes (et non des lectures de ... 0 octets ). Lorsque je questionne le 333, il met parfois plus de 500ms à répondre, et jusque 1000ms (je pense que cela dépend où en est son firmware interne. Je doute qu'on puisse aller plus vite que ce que donne la doc comme limite de rafraichissement des données (1000ms).  Le 600ms est donc je pense trop "rapide", et inutile. Une fois sur deux vous ne lisez pas toutes les données (quand ce n'est pas juste zéro data).

Pour faire "mieux" et "en temps réel", la seule solution est celle qu'André propose en monophasé avec bobine etc.. et la multiplier par trois. pas sûr que cela en vaille la peine pour quelques dizaines de watts par-ci par-là. Et encore moins quand des nuages passent... Cry

Edit : je vous relis et comprend qu'en questionnant seulement quelques données, et en deux fois, et à 400ms, les données reçues varient toutes ?
Si tel est le cas, oui la doc est erronée ou incomplète. Et c'est une bonne nouvelle. Vous avez donc résolu votre problème d'appel en deux fois ?

De mon coté, je bataille avec UxIx3 en serveur, avec trois routeurs clients, et de multiples plantages que je n'avais pas en V8.09 dès que j'affiche de multiples pages html sur l'ordi et/ou le smartphone. Edit : Problème solutionné en repassant le serveur UxIx3 en version V9.01 et la bibliothèque ESP32 associée.
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
#16
Voilà ce matin, alors que la production de mes 6 panneaux a commencé$

ce que voit le Linky ( pas d'injection )
   

ce que mesure et reporte le JSY-MK-333 ( le soutirage complet, et l'injection complète, avec la puissance apparente "corrigée" par logiciel )
   

et ce que calcule le logiciel en parallèle "à la manière Linky"
   

Attention, tout n'est pas pris exactement à la même heure, d'où les petits écarts. 
Sinon, pour moi, le compte est bon...
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
#17
J'ai repris votre code et l'ai fusionné au mien, en ne lisant que les données nécessaires et en faisant les calculs en binaire, c'est parfaitement stable avec un délai de 400ms défini dans le ino principal
les mesures de conso et injection semblent fiable, je vais tester sur plusieurs jours !

Code :
// *************************************************
// * Client lecture JSY-MK-333 * Triphasé *
// * Développement initial de Pierre F (Mars 2024) *
// * update PhDV61 Juin 2024 *
// *************************************************


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

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 i;
byte msg_send[] = { 0x01, 0x03, 0x01, 0x09, 0x00, 0x30, 0x94, 0x20 };
for (i = 0; i < 8; i++) {
MySerial.write(msg_send[i]);
}

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

if (a == 101) { //message complet reçu
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

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

if (injection) {
PuissanceS_M_inst = 0;
PuissanceI_M_inst = float((Lecture333[3] << 24) + (Lecture333[4] << 16) + (Lecture333[5] << 8) + Lecture333[6]);
// 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((Lecture333[3] << 24) + (Lecture333[4] << 16) + (Lecture333[5] << 8) + Lecture333[6]);
// 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) ;
}


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>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>Données reçues : " + String(a) + "</br>";
MK333_dataBrute += "<br>Number of bytes : " + String(Lecture333[2]) + "</br>";

Pva_valide=true;
filtre_puissance();
esp_task_wdt_reset(); //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));
}
}
Répondre
#18
Vous m’impressionnez les gars. Merci, je suis incapable de faire ça !
--------------------------------------------------------------
ESP32 (v11.17 et IP fixe) + sonde température + SSR -- Cumulus/Chauffe-Eau
Source données serveur Enphase 7.

Répondre
#19
(16-06-2024, 12:29 PM)piamp a écrit : J'ai repris votre code et l'ai fusionné au mien, en ne lisant que les données nécessaires et en faisant les calculs en binaire, c'est parfaitement stable avec un délai de 400ms défini dans le ino principal
les mesures de conso et injection semblent fiable, je vais tester sur plusieurs jours !

Code :
// *************************************************
// * Client lecture JSY-MK-333 * Triphasé *
// * Développement initial de Pierre F (Mars 2024) *
// * update PhDV61 Juin 2024 *
// *************************************************


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

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 i;
byte msg_send[] = { 0x01, 0x03, 0x01, 0x09, 0x00, 0x30, 0x94, 0x20 };
for (i = 0; i < 8; i++) {
MySerial.write(msg_send[i]);
}

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

if (a == 101) { //message complet reçu
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

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

if (injection) {
PuissanceS_M_inst = 0;
PuissanceI_M_inst = float((Lecture333[3] << 24) + (Lecture333[4] << 16) + (Lecture333[5] << 8) + Lecture333[6]);
// 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((Lecture333[3] << 24) + (Lecture333[4] << 16) + (Lecture333[5] << 8) + Lecture333[6]);
// 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) ;
}


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>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>Données reçues : " + String(a) + "</br>";
MK333_dataBrute += "<br>Number of bytes : " + String(Lecture333[2]) + "</br>";

Pva_valide=true;
filtre_puissance();
esp_task_wdt_reset(); //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));
}
}

Parfait.
Je suggère que vous ajoutiez un StockMessage(" heure d'arrivée message complet "+String( millis()/1000) );
pour vérifier que vous avez bien un nouveau message valide toutes les 400ms. J'ai un gros doute, car c'est ce qui se passe avec 141 data requises toutes les 600ms. Il en manque...

Sinon, un octet c'est 8 bits, et sur une ligne série, il commence souvent par un "start bit" et se termine par un "stop bit" soit 10 bits en tout.
A 19200 bauds, 192 octets (= 1920 bits) prennent environ 100 ms. Soit un octet toutes les 0.5ms environ. C'est très très long par rapport à la capacité d'un ESP32 à plusieurs dizaines de MHz.
A 9600 bauds, c'est 200ms, soit bien inférieur aux requêtes chaque 600ms. Et pourtant, il manque des réponses aux requêtes lorsqu'on questionne plus vite. Donc ce n'est peut-être pas 1s comme dit la doc, mais peut-être que le 1s est "garanti", alors que toute requête plus rapide est servie "seulement si c'est possible" par rapport à ce qu'est entrain de faire le uC du JSY-MK-333 à ce moment-là. en tout cas, c'est ce que j'ai constaté.
Plus j'essaie de m'écarter des 1000ms, plus il manque des messages ( avec a=0 d'ailleurs, comme si le JSY-MK-333 ignorait purement et simplement la requête. D'ailleurs, si on ne relance pas à nouveau une requête, on ne recevra alors plus rien en réponse comme je l'ai testé).
Cdlt,
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
#20
Pour illustrer mon propos ci-dessus, voilà ce que donne la décorrélation de la requête d'une part, et l'attente de la réponse d'autre part :

Le temps indiqué à droite est le temps mesuré entre deux messages reçus. L'heure à laquelle la requête avait été faite est sur la gauche.
On voit que parfois le module répond 200ms après la requête. Parfois 400ms... Au vu de la répétibilité des timings, il semblerait que la latence de réponse dépend du moment où la requête est envoyée au module ( qui la traite lorsqu'il en a envie... Normal, c'est totalement asynchrone tout ça).

   

Même en lisant 141 valeurs, le module répond parfois rapidement (200ms), ce qui est cohérent avec la vitesse de transmission, mais parfois il tarde jusqu'à ... 800ms. Et on n'y peut rien.  J'ai mis un timer d'attente à 600ms, et je viens vérifier toutes les 100ms si la réponse a été reçue.

Peut-être qu'en doublant la vitesse de transmission le module répond deux fois plus vite.  ou pas.
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


Atteindre :


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