AQUABOUN'S /// GESTION D'AQUARIUM RECIFAL

j'ai fait

NexText*tableauLigneAffichageSd[] = {&valeursd00,&valeursd01,&valeursd02,&valeursd03,&valeursd04,&valeursd05,&valeursd06,&valeursd07,
&valeursd08,&valeursd09,&valeursd10,&valeursd11,&valeursd12,&valeursd13,&valeursd14,&valeursd15,&valeursd16,&valeursd17};

puis

tableauLigneAffichageSd[ligneNextion-1].setText(donneeLueSurSD);

et j'ai

request for member 'setText' in 'tableauLigneAffichageSd[(((int)ligneNextion) + -1)]', which is of pointer type 'NexText*' (maybe you meant to use '->' ?)

on a mis des pointeurs dans le tableau pas les objets directement, donc il faut mettre

tableauLigneAffichageSd[ligneNextion-1][color=red]->[/color]setText(donneeLueSurSD);

YEs, merci

et pour le ficher sd, comment faire soit pour lire a l'envers soit pour ecrir en haut a chaque ajout ?

et pour le ficher sd, comment faire soit pour lire a l’envers soit pour ecrir en haut a chaque ajout ?

On ne peut pas écrire en haut à chaque ajout, on écrit toujours à la fin.

Tenez voici un bout de code de démo qui prend la technique du fichier d’index pour lire à l’envers.

(.ino attaché en PJ)

Il y a des constantes importantes pour la gestion des Index ou de l’affichage

const uint8_t nombreDeLignesAffichage = 10; // le nombre de ligne dans une page d'affichage
const uint8_t tailleMaxLigne = 80; // le nombre max de caractère dans une ligne de la page

L’idée est un affichage du fichier de log par ‘pages’ donc il faut connaître la taille d’une page. ici je dis qu’une page c’est 10 lignes.
Ensuite j’ai décidé de forcer un buffer de taille fixe par ligne pour l’affichage (pas forcément dans le log) est ici c’est 80.

Au début dans le setup il faut appeler prepareFichiersLog("bla bla bla en tête", booléen).
Si le booléen est vrai, on détruit les fichiers de logs s’ils existaient. (donc attention !)
Si le booléen est faux et que les 2 fichiers existent déjà, on ne fait rien, mais si un des deux fichier n’est pas là alors on détruit celui qui existe (attention donc!) et on prépare un fichier d’index avec juste 0x00000000 dedans puisque que ce sera le début de la première page du fichier de log et enfin on écrit l’en tête du fichier de log avec “bla bla bla en tête”

Une fois cela fait, il y a une fonction logMessage("ce que l'on veut mettre dans le log") qui écrit dans le fichier de log et qui se charge de maintenir le fichier d’index pour vous. c’est ce qu’il faut utiliser dans le programme à chaque log. Attention il ne faut pas de saut de ligne au sein du message (il faut donc avoir bâti dans un cString ce que l’on veut écrire).

Dans ce fichier d’exemple, j’ai rajouté à la fin de prepareFichiersLog() un petit bout de code pour remplir mon fichier de log avec plus de 2000 lignes pour la démo

 // ici on triche et on pré-rempli le fichier, à enlever bien sûr
  char message[100]; // un buffer assez grand pour notre message
  for (int i = 1; i < 2023; i++) { // 24 pages de 10, la dernière n'ayant que 7 lignes (ligne d'en tête dans le fichier de log)
    sprintf(message, "%03d\tles valeurs sont A0=%d et A1=%d\t{%ld}", i, analogRead(A0), analogRead(A1), random(-32000, 32000));
    logMessage(message);
  }
  Serial.println("Fichier de log de démo créé avec 2023 lignes");

cette création prend un peu de temps bien sûr car je voulais un fichier de log assez important.

Voilà. La loop est toute simple, elle attend un caractère sur la console série à 115200 bauds. tapez ‘d’ pour lire la page de début, ‘f’ pour lire la page de fin, ‘+’ ou ‘s’ pour lire la page suivante et ‘-’ ou ‘p’ pour lire la page précédente.

Le fichier de log s’appelle “log.txt” et celui d’index associé est “_log.txt”

je vous laisse essayer (ne prenez pas votre carte SD de votre système, je ne veux pas être responsable de son effacement :slight_smile: )

Vous verrez que c’est assez rapide d’accéder à la dernière page (‘f’) et de remonter (’-’) malgré le fait que l’on ait plus de 2000 lignes dans le fichier

essayez de faire ‘f----++±—’ par exemple et vous verrez que ça speed pas mal :slight_smile:

On pourrait envisager facilement un petit bout de code à exécuter une fois séparément qui lit votre fichier de log existant et construit l’index de façon à ce que vous puissiez intégrer la nouvelle fonctionnalité sans avoir à détruire le log existant.

SD_LogAndScroll.ino (8.86 KB)

bonjour,

je retravaille depuis peu sur le projet. Je reprend donc la partie affichage des erreur. J'ai voulu faire par moi même :stuck_out_tongue:

tout les messages écrit avait la même taille (100 caractères) je me plaçait au dernier caractere du fichier je remontait de 100 pour lire une ligne et l’afficher puis remontait de 100 ect ...

La première page (18 lignes) etait ok mais des que je voulait changer de page rien n'allait alors que j'utilisait toujours le même principe. De plus, avec cette méthode aucune vérification pour savoir si l'emplacement était ok par exemple si l'arduino reboot au milieu d'une écriture tout la lecture est ensuite décalé ...

Je me suis donc mis sur le code joint par JML Le principe est compris mais le code est un peu dur a déchiffrer et donc a l'adapter ...

J'aurais besoin de quelque info pour être sur :

chaque ligne écrit doit être précéder de chiffre ? Pour écrire le message je lance la fonction avec mon char* >>> logMessage(bufferTexte);, j'ai bon ? Le fichier index ne s'enrichi que lorsque ont a atteint le nombre de ligne indiquer ? >>> si oui, je pense que mon problème vient de la puisque J'ecrit ligne par ligne cela veut dire que temps que je n'ai pas écrit assez de ligne elle ne sont pas indexer ?

J'aurais besoin de quelque info pour être sur :

chaque ligne écrit doit être précéder de chiffre ? Pour écrire le message je lance la fonction avec mon char* >>> logMessage(bufferTexte);, j'ai bon ? Le fichier index ne s'enrichi que lorsque ont a atteint le nombre de ligne indiquer ? >>> si oui, je pense que mon problème vient de la puisque J'ecrit ligne par ligne cela veut dire que temps que je n'ai pas écrit assez de ligne elle ne sont pas indexer ?

Je suis sur mon portable donc je ne peux pas voir mon ancien code

De mémoire cependant le fichier de log est non contraint au niveau contenu, l’analyse se fonde sur les saut de ligne: une ligne = un Élément de message

Comme expliqué plus haut il y a une fonction logMessage qui se charge d’écrire dans le fichier log et de maintenir le fichier d’index. Cependant pour que cela fonctionne il faut avoir crée correctement le fichier d’index, donc cf ce qu’il y a dans mon setup()

Le fichier d’index est un fichier binaire qui contient les positions des débuts de lignes du fichier de log: Sur les octets 0 à 3 on a 0x00000000 puisque la première ligne est à l’octet 0. Sur les octets 4 à 7 on a la position du début de deuxième ligne. Sur les octets de 8 à 11 la position du début de la troisième ligne Etc. Donc de manière générale comme Chaque position est codée sur 4 octets si on veut savoir où commence la Nème ligne, il suffit d’aller lire un unsigned long dans le fichier d’index à la position 4*(N-1) (ou 4*N si on considère que la première ligne est la ligne 0)

Est-ce plus clair ?

J’ai verifier et tout est bien dans le setup
Le comptenu (donc l’ecriture) du fichier erreur est bon aussi
L’index semble egalement bon car plus le temps passe et plus il y a de ligne.
Le problème vient donc de la lecture car j’ai des ligne blanche :

'index de la page 0 est 0
PAGE: 0
Ligne 0	
Ligne 1	
Ligne 2	
Ligne 3	
Ligne 4	
Ligne 5	
Ligne 6	
Ligne 7	
Ligne 8	
Ligne 9	
Ligne 10	
Ligne 11	
Ligne 12	
Ligne 13	
Ligne 14	
Ligne 15	
Ligne 16	
Ligne 17	
Demande lecture page 1
L'index de la page 1 est 1203
PAGE: 1
Ligne 0	
Ligne 1	
Ligne 2	
Ligne 3	
Ligne 4	
Ligne 5	
Ligne 6	
Ligne 7	
Ligne 8	
Ligne 9	
Ligne 10	
Ligne 11	
Ligne 12	
Ligne 13	
Ligne 14	
Ligne 15	
Ligne 16	
Ligne 17

Pourtant j’ai bien vérifier et rien n’as été modifié.

Bonsoir,

J'ai passer la journée sur l'affichage. il a fallu adapter beaucoup de chose mais je partait sur de bonne base (merci jml) Le code de base lit de haut en bas (donc du plus ancien au plus récent) un certain nombre de ligne correspondant a une page. En retournant l'ordre de lecture ( le plus récent afficher en haut) je me suis retrouver avec pas mal de problème a contourner. Au final tout cela est régler et la seul trace visible est que lorsque on change de page pour revenir l'écriture se fait de bas en haut ... https://www.youtube.com/watch?v=SFF3snY8Q2U

Bravo !!

J-M-L: Bravo !!

Oula ... merci mais cette félicitation veux dire que le "bug" que je traine depuis un bon moment n'as pas été vu :stuck_out_tongue: regarder bien le début des lignes température :) Encore un problème avec l'écriture d'un char ... mais j'ai trouvé, je faisait un strncpy_P au lieu de strcat

Donc ce qui me reste avant de partager cette nouvelle version :

vérifier la fiabilité du nouveau module de mesure PH (attente du nouveau PCB pour ca) vérifier la fiabilité du nouveau module de mesure ORP (attente du nouveau PCB pour ca) écriture de tout la partie étalonnage du module ORP écriture de toute la gestion, affichage et calibration du module de mesure de la densité check de l'intégralité du code / mise en page / commentaire ...

Mais avant cela je voulait terminer la partie "configuration" et le dernier point qui a poser problème alors que j'ai fait comme pour tout le reste est le choix des PIN, je m'explique : J'ai crée 3 fichier "pin" définissant chacun des PIN diffèrent en fonction des branchement de chacun PinUtilisateur.h PinPCBouns15.h PinPCBouns20.h Dans la configuration.h j'ai fait

//#define PinPCBouns15
//#define PinPCBouns20
//#define PinUtilisateur

ou l'utilisateur doit décommenter la ligne correspondant a sa configuration. puis dans chaque Pin*.h j'ai fait un #ifdef pin** et #endif

Mais lors de la compilation j'ai un mess d'erreur que les pin ne sont pas définis. peut importe qu'elle configuration est choisie

Il y a une exception pour la définition des pin ?

Oula ... merci mais cette félicitation veux dire que le "bug" que je traine depuis un bon moment n'as pas été vu :stuck_out_tongue: regarder bien le début des lignes température :)

un peu petit sur mon smartphone.... j'avais juste vu que ça affichait des trucs ! c'est quoi le souci, la T° à Zéro degré ?

strncpy_P() c'est pour ce qui se trouve en PROGMEM. attention sur une MEGA quand on commence à avoir bcp de texte, on peut se retrouver dans les segments 'far' et ça fiche un peu le bazar...

je n'ai pas bien compris comment vous gérez vos 3 fichiers.

Vous pourriez faire comme cela:

Vous définissez vos 3 fichiers de PINS

``` PinUtilisateur.h ```

#ifndef PinUtilisateur_h
#define PinUtilisateur_h
const byte pinToto = 3;
const byte pinTutu = 5;
#endif

``` PinPCBouns15.h ```

#ifndef PinPCBouns15_h
#define PinPCBouns15_h
const byte pinToto = 7;
const byte pinTutu = 4;
#endif

``` PinPCBouns20.h ```

#ifndef PinPCBouns20_h
#define PinPCBouns20_h
const byte pinToto = 22;
const byte pinTutu = 25;
#endif

et dans ``` configuration.h ``` vous pourriez avoir une inclusion conditionnelle du bon fichier .h

#ifndef configuration_h
#define configuration_h

// CHOISIR LA CONFIGURATION DES PINS SOUHAITÉE EN ENLEVANT LE COMMENTAIRE  
//#define PinUtilisateur
//#define PinPCBouns15
//#define PinPCBouns20


#if defined(PinUtilisateur)
  #include "PinUtilisateur.h"
#elif defined(PinPCBouns15)
  #include "PinPCBouns15.h"
#elif defined(PinPCBouns20)
  #include "PinPCBouns20.h"
#endif

#endif

Le souci avec le mess température était qu'il manquait le début et a la place il y avait un caractere. j'ai effectivement pas mal de texte en PROGMEM ( une centaine) mais il ne font entre 10 et 40 caractères chacun. Je n'ai pas vu de bug a se niveau la (sauf ceux dont j'était responsable lol)

pour ma gestion des PIn*.h

Dans mon configue.h j'avais

#ifndef  _config_h_
#define _config_h_
// Choix de la configuration des PIN de l'arduino
/*choisir le type de configuration des pin correspondant a votre montage */ // ne choisir qu'une configuration
//#define PinUtilisateur
//#define PinPCBouns15
#define PinPCBouns20
#endif

puis dans chaque pin***.h

#ifdef PinPCBouns15

const uint8_t pinInCoupureCourant = A4; // entree presence tension d'alimentation
const uint8_t pinInBatterie = A5; // entree niveau batterie
const uint8_t pinInPhBac = A6; // entree sonde PH BAC
.......
....
#endif

et j'avais un message que xxx PIN n'était pas défini…

J'ai modifier pour concorder a ton dernier message. et j'ai la même chose

'pinOutRelaisElectovanneRac' was not declared in this scope

correspondant a une ligne du setup

  pinMode(pinOutRelaisElectovanneRac, OUTPUT); // Définit la broche comme sortie

quand et où importiez vous les pin***.h dans votre approche ?

avec mon approche vous avez bien noté qu’il y a un _h dans le define du ifdef du ficher ? (ce n’est pas le même que le #define PinUtilisateur du fichier de config, sinon ça importera pas)

#ifndef PinUtilisateur_h
#define PinUtilisateur_h // ATTENTION CE N'EST PAS LE MEME QUE #define PinUtilisateur

Je mets en PJ un projet avec plusieurs fichiers à fins de démonstration

si dans le fichier de configuration vous mettez

// CHOISIR LA CONFIGURATION DES PINS SOUHAITÉE EN ENLEVANT LE COMMENTAIRE  
#define PinUtilisateur
//#define PinPCBouns15
//#define PinPCBouns20

alors quand vous le faites exécuter vous verrez dans la console

[color=purple]pinToto = 3
pinTutu= 5[/color]

mais si vous mettez

//#define PinUtilisateur
#define PinPCBouns15
//#define PinPCBouns20

alors quand vous le faites exécuter vous verrez dans la console

[color=purple]
pinToto = 7
pinTutu= 4
[/color]

enfin si vous mettez

//#define PinUtilisateur
//#define PinPCBouns15
#define PinPCBouns20

alors quand vous le faites exécuter vous verrez dans la console

[color=purple]pinToto = 22
pinTutu= 25[/color]

donc ça fonctionne bien

testPin.zip (1.67 KB)

j'avais bien vu le _h

J'ai eu beau chercher d'où venait le problème, faire des retours en arrière, je n'ai pas trouvé d'où venait le problème alors que tout semblait concorder ... bref sa fonctionne bien a présent, merci

J'ai constater une anomalie aléatoire entre les échanges ecran > arduino. Dans la page paramétrage de l'ecran, l'arduino envoie les variables actuels. On modifie ces variables a partir de l'ecran et lorsque tout est ok, on click sauvegarder. a se moment la l'arduino demande au nextion la valeur d'un champ, nextion lui envoie et l'arduino le copie dans la variable correspondante et ainsi de suite jusque a avoir récupérer toute les variable de l'ecran. Lorsque toute les variable modifier a l'ecran on été récupérer elle sont sauvegarder.

de manière aléatoire, il arrive régulièrement que la première valeur récupérer reste identique le temp de 3 ou 4 autre demandes et du coup puis la 5eme va faire de même 3 ou 4 fois ect ...

exemple a l'ecran on a:

A = 1
B = 2
C = 3
D = 4
E = 5
F=  6

sauvegarder dans l'arduino il y auras si "bug"

A = 1
B = 1
C = 1
D = 1
E = 5
F=  5
ect ...

Apres avoir un peu chercher, utiliser le debug, J'en arrive a la conclusion que l'arduino va trop vite / nextion trop lent Comme si le nextion renvoyait la valeur précèdent pars qu'il n'avait pas eu le temps de lire car par exemple il suffit que je rajout un ligne debug entre chaque demande/réception pour que le problème disparaisse. La solution serait donc de mettre un petit délais entre chaque mais je ne veux pas mettre un pansement si cela n'est pas normal.

Qu'en penser vous ?

pour info : Les échange arduino nextion sont en 115200 baud

J'en arrive a la conclusion que l'arduino va trop vite / nextion trop lent

ils vont à la même vitesse au niveau communication mais il se peut que le logiciel de l'écran créée un liste de tâches à effectuer en fonction des commandes arrivant sur son port série (en faisant le parsing plus tard pour vider le buffer d'entrée) et s'il donne la priorité aux requêtes d'information (qui sont synchrone je crois) plutôt qu'à celles de mises à jour de valeurs alors ça vous donne le comportement que vous voyez....

est-ce qu'il y a moyen d'attendre un accusé de réception d'une commande de mise à jour de l'écran ?

mais connaissance ne me permette pas d'être affirmatif. Mais meme si c'est le cas, rien du coté de l'aquabouns pour gerer en cas d'erreur ...

J'ai regarder dans la bibliothèque et ci dessous l'extrait de se que je pense utiliser comme fonction lorsque je fait une demande :

bool NexNumber::getValue(uint32_t *number)
{
    String cmd = String("get ");
    cmd += getObjName();
    cmd += ".val";
    sendCommand(cmd.c_str());
    return recvRetNumber(number);
}
bool recvRetNumber(uint32_t *number, uint32_t timeout)
{
    bool ret = false;
    uint8_t temp[8] = {0};

    if (!number)
    {
        goto __return;
    }
    
    nexSerial.setTimeout(timeout);
    if (sizeof(temp) != nexSerial.readBytes((char *)temp, sizeof(temp)))
    {
        goto __return;
    }

    if (temp[0] == NEX_RET_NUMBER_HEAD
        && temp[5] == 0xFF
        && temp[6] == 0xFF
        && temp[7] == 0xFF
        )
    {
        *number = ((uint32_t)temp[4] << 24) | ((uint32_t)temp[3] << 16) | (temp[2] << 8) | (temp[1]);
        ret = true;
    }

__return:

    if (ret) 
    {
        dbSerialPrint("recvRetNumber :");
        dbSerialPrintln(*number);
    }
    else
    {
        dbSerialPrintln("recvRetNumber err");
    }
    
    return ret;
}

ils semble qu'il y ait des soucis à en lire les bugs ouverts... (par exemple ceci)

j'utilise pas nextion car c'est limité au PC et les commentaires de ceux de la communauté Arduino qui ont essayé de travailler avec eux pour améliorer la bibliothèque ont été édifiants...

:o

il parle d’une bibliothèque “NeoNextion” qui serait mieux …
Mais cela voudrait dire tout revoir :confused: :cold_sweat:

oui.... pour la V5 :)

J-M-L: oui.... pour la V5 :)

:sweat_smile: :sweat_smile: :sweat_smile: oui j'aurais du temp a la retraite :grinning: :grinning: :grinning:

pour "solutionner" le bug j'ai ajouter un délais. Apres diffèrent essaie, a partir de 250ms je n'ai plus le bug. C'est assez long !!! surtout quand il y a 22 champs a récupérer ... Mais, visuellement, quand on click enregistrer j'avais une barre de progression qui se remplissait en ~2sec et elle n'était la que visuellement pour que l'utilisateur visualise bien que la sauvegarde était en cours (sans cela on revenais d'un coup a la page précédente et cela pouvait nous faire douter je trouvais) J'ai donc allonger la progression de cette barre ~5sec comme cela visuellement la barre de progression bouge et en même temps l'arduino fait ces demande/delay. Pour l'utilisateur, les delays sont donc invisible :)