Une histoire de loop qui casse les ...

Coucou tout le monde

J’ai cédé au charme d’un écran tactile LCD de 4D systems (le LCD43-PT) et son fameux Visi-Genie.
Si mettre en place images/boutons/sons/… est un jeu d’enfant, la communication avec l’Arduino est beaucoup plus trash, surtout pour quelqu’un comme moi qui n’a jamais fait de langage C.

J’en appel aux pros de la programmation, pour qui le langage Arduino est une seconde langue maternelle. XD

Sur le papier c’est très simple. Pour changer les propriétés d’un objet il suffit de passer la commande “SendMessage (Code de l’action, Code de l’objet, Valeur à transmettre)”
Ca marche trés bien pour UN SEUL objet. Mais (car il y a ce foutu ‘mais’) si je met plusieurs “Sendmessage” à la suite, seul le premier objet est modifié et aucun autres !.

J’ai donc fais un double tableau ( tableau 1 = codes de tous les objets et tableau 2 = toutes les valeurs a transmettre) pour tout passer d’en seul coup sous la forme d’une fonction “Void Afficher()”

Et la plus rien ! plus aucun objets n’est modifié ! J’ai beau trifouiller depuis des jours, rien !

Voici le code :

// *********************************************
// INCLUDE
// *********************************************

#include “SoftwareSerial.h”
#include “Arduino.h”

// *********************************************
// CONSTANTES
// *********************************************
#define DisplaySerial Serial
SoftwareSerial mySerial (0,1); // RX, TX du Shield LCD

#define READ_OBJ 0x00 // code actions entre le LCD et l’arduino
#define WRITE_OBJ 0x01
#define REPORT_OBJ 0x05
#define REPORT_EVENT 0x07

const uint16_t Gauge0 = 0x0B00;
const uint16_t Gauge1 = 0x0B01;
const uint16_t Gauge2 = 0x0B02;
const uint16_t Gauge3 = 0x0B03;
const uint16_t Gauge4 = 0x0B04;
const uint16_t Gauge5 = 0x0B05;
const uint16_t Gauge6 = 0x0B06;
const uint16_t Gauge7 = 0x0B07;
const uint16_t Gauge8 = 0x0B08;
const uint16_t Gauge9 = 0x0B09;
const uint16_t Gauge10 = 0x0B0A;
const uint16_t Gauge11 = 0x0B0B;
const uint16_t Gauge12 = 0x0B0C;
const uint16_t Gauge13 = 0x0B0D;
const uint16_t Gauge14 = 0x0B0E;
const uint16_t String0 = 0x1100;
const uint16_t String1 = 0x1101;
const uint16_t String2 = 0x1102;
const uint16_t String3 = 0x1103;
const uint16_t String4 = 0x1104;
const uint16_t String5 = 0x1105;
const uint16_t String6 = 0x1106;
const uint16_t String7 = 0x1107;
const uint16_t String8 = 0x1108;
const uint16_t String9 = 0x1109;
const uint16_t String10 = 0x110A;
const uint16_t String11 = 0x110B;
const uint16_t String12 = 0x110C;
const uint16_t String13 = 0x110D;
const uint16_t String14 = 0x110E;
const uint16_t String15 = 0x110F;

// *********************************************
// VARIABLES
// *********************************************

uint8_t command;
uint16_t object, value;
boolean flag;
int Temperature;
unsigned int val;

// *********************************************
// FONCTIONS
// *********************************************

// Recuperer les ACK : 0xc6 (06 = succes) ou 0xd5 (15 = echec)
uint8_t nacAck() {delay (10);while(!mySerial.available());return mySerial.read();}

// READMESSAGE = Lecture des infos envoyées par le LCD
bool readMessage(uint8_t &command0,uint16_t &object0, uint16_t &value0) {
bool flag0=false;uint8_t buffer[6];uint8_t checksum = 0x00;uint8_t i=0;
if(mySerial.available()>0) {buffer = mySerial.read();command0 = buffer[0];i++;checksum = command0;
if (command0==REPORT_EVENT){
if(mySerial.available()>3) {buffer = mySerial.read();checksum ^= buffer;i++;object0 = buffer[1]<<8 | buffer[2];buffer = mySerial.read ();checksum ^= buffer;i++;object0 = buffer[1]<<8 | buffer[2];buffer = mySerial.read();checksum ^=buffer*;i++;*
value0 = buffer[3]<<8 | buffer[4];}}flag0 = (checksum==mySerial.read());}return flag0;}
// SENDMESSAGE = Envoi des messages au LCD
bool sendMessage(uint8_t command0, uint16_t object0, uint16_t value0) {
bool flag0 = false;uint8_t buffer[6];uint8_t checksum = 0x00;uint8_t i=0;buffer = command0;checksum = command0;i++;buffer = object0 >>8;checksum ^= buffer*;i++;*
buffer = object0 & 0xff;checksum ^= buffer;i++;buffer = value0 >>8;checksum ^= buffer;i++;buffer= value0 & 0xff;checksum ^= buffer_;i++;buffer = checksum;i++;
mySerial.write(buffer, i); return(nacAck()==0x06);
}
// AFFICHER = envoyer les valeurs aux objets du LCD
uint16_t a;
const int MaxItem = 47; // Nombre total des objets a afficher = taille du tableau_

const uint16_t NoItem[42]= {0x0B00,0x0B01,0x0B02,0x0B03,0x0B04,0x0B05,0x0B06,0x0B07,0x0B08,0x0B09,0x0B0A,0x0B0B,0x0B0C,0x0B0D,0x0B0E,0x1100,0x1101,0x1102,0x1103,0x1104,0x1105,0x1106,0x1107,0x1108,0x1109,0x110A,0x110B,0x110C,0x110D,0x110E,0x110F};
** uint16_t Valeur[42]= {0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x001A,0x001A,0x000A,0x0010,0x0010};**

void afficher () { // Boucle pour afficher la valeur des item
** for(int compt=0; compt<MaxItem; compt++) {**
** Serial.println(NoItem[compt]);**
** Serial.println("–");**
** Serial.println(Valeur[compt]);}**
** for(int compt=0; compt<MaxItem; compt++) {**
** sendMessage(WRITE_OBJ, NoItem[compt], Valeur[compt]);
_
delay (10);}
};**_

// *********************************************
// VOID SETUP
// *********************************************
void setup() {
mySerial.begin(9600);
*delay (3000); *
}
// *********************************************
// VOID LOOP
// *********************************************
void loop() {
afficher();
sendMessage(0x0001, 0x0A00, 0x0015); // Toute seule, cette fonction marche
delay(500);
}
Est ce que vous avez vu une c… dans le code ?. J’ai tellement le nez dessus depuis plusieurs jours que j’y arrive plus. ]:smiley:
Toute remarque sera la bienvenue.
Merci d’avance

Tiens, le fait de prendre un peu de hauteur, je viens de voir une betise :

const int MaxItem = 47; il faut lire const int MaxItem = 42;

Vous voyez autre chose peut être ?

Sans être allé au fond de ton code, les symptômes me font penser à un problème de NacAk.
Le nombre de byte envoyé n'étant pas celui attendu par la dalle.

J'avais le même soucis lorsque j'envoyais une commande de modification du contraste (format différent),
ce qui m'avait obligé de créer une fonction spécifique.

Moi je dirais surtout déjà que ça

SoftwareSerial mySerial (0,1); // RX, TX du Shield LCD

C’est une grosse boulette si tu as une UNO car pin 0 et 1 il y a … la liaison série hardware. Il vaut mieux utiliser d’autres pin, c’est le but de softserial.h

Après c’est pas forcement la cause du problème

EDIT : en plus dans afficher tu te sers du série hardware, pas étonnant que ça marche encore moins puisqu’il n’y a pas de Serial.begin() dans le setup()

Est ce que tu peux éditer tes messages et mettre le code entre les balises “code” avec le bouton #

@ Jean-Francois : oui, je vois de quoi tu parles. Promis j'y penserais la prochaine fois
@ B@tto : j'ai une Mega2560
@Bubulle : J'ai lu un truc comme ça sur un tutorial de 4D systems. Tu as certainement une bonne idée (ça sent le vecu toussa ?! :D) Je part chercher....

Est ce que vous voyez une autre bêtise qui pourrait expliquer que cette instruction ne fonctionne que toute seule et pas sous la forme d'une routine ?

Merci a ceux qui ont déja remarqué ça

sendMessage(0x0001, 0x0A00, 0x0015); // Toute seule, cette fonction marche
sendMessage(WRITE_OBJ, NoItem[compt], Valeur[compt]); //Ne marche pas

Donc au début du code #define WRITE_OBJ 0x01 est à remplacer par #define WRITE_OBJ 0x0001

@Bubulle : je ne m'en souvenais plus mais j'avais déjà intégré une fonction NakAcK (). Dommage c'était une très bonne idée.
@Christian_R : dans les deux cas, la fonction seule fonctionne et pas la routine même avec la modification que tu m'as suggérer

J'ai posté sur le support de 4D systems mais personne ne me répond =(

Voyez-vous une autre co(q)uille dans ma routine ?. Elle est pourtant très simple. Elle devrait marcher non ?

Et en rallongeant le delay (10) ?

Après des jours et des jours la dessus, je jette l’éponge écœuré.
J’ai fini par faire tourner ma routine mais elle ne semble pas capable de modifier plus d’un objet et la faute n’est pas coté Arduino.

Visiblement le SAV de 4D systems se contrefout des ennuies que l’on peut rencontrer sous Arduino avec leur écran.

J’ai vu ton post Bubule ou tu avais utilisé la librairie genieArduino.h. Cette librairie semble toute ressente. J’ai vu aussi ton code pour la gestion d’un aquarium.

Il va falloir que je réécrive une bonne partie et ce d’autant plus qu’elle semble incompatible avec la SoftwareSerial.h
Et ça commence mal, j’ai déjà un défaut de compilation dès la déclaration des variables :~

As tu eu ces mêmes problèmes au début ? Est ce qu’ils sont enfin résolus ?

Merci d’avance

Les code est formaté de manière à masquer un maximum les erreurs. Une ligne par instruction et un code indenté correctement aiderait à la traque des soucis.

Les fonctions readmessage et sendmessage sont bizarre à mon sens.

SENDMESSAGE
tu fais incrémenter un index i à chaque élément que tu traites mais tu ne l’utilises pas. je pense qu’il faudrait utiliser i pour indexer buffer.

// SENDMESSAGE = Envoi des messages au LCD
bool sendMessage(uint8_t command0, uint16_t object0, uint16_t value0) {
       bool flag0 = false;
       uint8_t buffer[6];
       uint8_t checksum = 0x00;
       uint8_t i=0;

       buffer[i] = command0;
       checksum = command0;
       i++;
       buffer[i] = object0 >>8;
       checksum ^= buffer;
       i++;
       buffer[i] = object0 & 0xff;
       checksum ^= buffer;
       i++;
       buffer[i] = value0 >>8;
       checksum ^= buffer;
       i++;
       buffer[i]= value0 & 0xff;
       checksum ^= buffer;
       i++;
       buffer[i] = checksum;
       i++;

       mySerial.write(buffer, i);
       return(nacAck()==0x06);
}

READMESSAGE
Il te faut 3 arguments en paramètres de REPORT_EVENT mais tu n’attends pas de les avoir reçu pour les lire. Si tu n’as pas 3 octets tu sors du if et tu quittes la fonction.
Il faut attendre d’avoir les 3 octets avant de continuer.

bool readMessage(uint8_t &command0,uint16_t &object0, uint16_t &value0) {
    bool flag0=false;
    uint8_t buffer[6];
    uint8_t checksum = 0x00;
    uint8_t i=0;

    if(mySerial.available()>0) {
    buffer = mySerial.read();
    command0 = buffer[0];
    i++;
    checksum = command0;
		if (command0==REPORT_EVENT){
			while (mySerial.available()<3); // attend 3 caractères
			buffer = mySerial.read();
			checksum ^= buffer;
			i++;
			object0 = buffer[1]<<8 | buffer[2];
			buffer = mySerial.read ();
			checksum ^= buffer;
			i++;
			object0 = buffer[1]<<8 | buffer[2];
			buffer = mySerial.read();
			checksum ^=buffer;
			i++;
			value0 = buffer[3]<<8 | buffer[4];
		}
		flag0 = (checksum==mySerial.read());
	}
	return flag0;
}

Le problème c’est que cela rend la fonction bloquante il faudrait peut être la reécrire avaec des fonction non bloquantes comme Serial.readBytes(). Mais cela compliquerait peut être un peu. Si ça fonctionne comme ça il ne faut peut être pas se compliquer.

ATTENTION code non vérifié

Bonjour

Ne désespères pas Yamasan. :astonished:
OUI, j’ai réussi à faire tout fonctionner :grin:
Pas sans mal (je ne suis qu’un bricoleur), mais j’ai réussi. Me reste à hiérarchiser pour gagner en réactivité tactile (j’ai 53 instructions envoyées).

Je te donne mon code issu de l’application faite par Avenue33 ici : http://www.4dsystems.com.au/downloads/Application-Notes/4D-AN-P4010-ViSi-Genie-Connection-to-a-Host-with-Red-Green-Blue-LED-Control-REV1.1.pdf
Celui-ci fonctionne avec softserial :wink:

// FONCTION RECEPTION MESSAGE LIAISON AFFICHEUR
  bool readMessage ( uint8_t &command0, uint16_t &object0, uint16_t &value0) {
    bool flag0 = false;
    uint8_t buffer[6];
    uint8_t checksum = 0x00;
    uint8_t i=0;
    
    if (SerialLCD.available()>0) {
        buffer[i] = SerialLCD.read();
        command0 = buffer[0];
        i++;
        checksum = command0;
         
         if (command0 == REPORT_EVENT) {
             if (SerialLCD.available()>3) {
                  buffer[i] = SerialLCD.read();
                  checksum ^= buffer[i];
                  i++;
                  buffer[i] = SerialLCD.read();
                  checksum ^= buffer[i];
                  i++;
                  object0 = buffer[1]<<8 | buffer[2];
                  buffer[i] = SerialLCD.read();
                  checksum ^= buffer[i];
                  i++;
                  object0 = buffer[1]<<8 | buffer[2];
                  buffer[i] = SerialLCD.read();
                  checksum ^= buffer[i];
                  i++;
                  value0 = buffer[3]<<8 | buffer[4];
               }
             }
             flag0 = (checksum==SerialLCD.read());
          }
            return flag0;
       }
 
 // FONCTION ENVOI MESSAGES VERS AFFICHEUR
  bool sendMessage (uint8_t command0, uint16_t object0, uint16_t value0) {
    
       bool flag0 = false;
       uint8_t buffer[6];
       uint8_t checksum = 0x00;
       uint8_t i=0;
       
       buffer[i] = command0;
       checksum = command0;
       i++;

       buffer[i] = object0 >>8;
       checksum ^= buffer[i];
       i++;

       buffer[i] = object0 & 0xff;
       checksum ^= buffer[i];
       i++;
       
       buffer[i] = value0 >>8;
       checksum ^= buffer[i];
       i++;
       
       buffer[i] = value0 & 0xff;
       checksum ^= buffer[i];
       i++;

       buffer[i] = checksum;
       i++;

       SerialLCD.write(buffer, i);
    
    return (nacAck()==0x06);
 }


// FONCTION ENVOI MESSAGES "CONTRAST" VERS AFFICHEUR
  bool sendContrast (uint8_t command0, uint8_t value) {
    
       bool flag0 = false;
       uint8_t buffer[3];
       uint8_t checksum = 0x00;
       uint8_t i=0;
       
       buffer[i] = command0;
       checksum = command0;
       i++;

       buffer[i] = value;
       checksum ^= value;
       i++;
       
       buffer[i] = checksum;
       i++;

       SerialLCD.write(buffer, i);
    
    return (nacAck()==0x06);
 }

Pour les instructions

 // Déclaration des éléments afficheur (Que j'ai positionné avant les fonctions)
  const uint16_t leddigith = 0x0900;            // 2 Digits "heure"
  const uint16_t leddigitm = 0x0901;            // 2 Digits "minutes"
  const uint16_t leddigits = 0x0902;            // 2 Digits "secondes" 

// Dans le loop
         sendMessage(WRITE_OBJ, leddigith, heureExt);
         sendMessage(WRITE_OBJ, leddigitm, minuteExt);       
         sendMessage(WRITE_OBJ, leddigits, secondeExt);

Pour le contraste

 sendContrast(0x04, 0x00);                // Coupe le contraste

Si çà peut aider

Franck

Vous etes formidables les gars :smiley:

J'ai fini par débloquer la situation en changeant la librairie. La GeniArduino.h est très simpliste mais au moins elle fonctionne. Partant de la, j'ai réussi à changer toutes les valeurs des objets en une seule routine en combinant mes 3 tableaux. Maintenant, je bataille pour faire la même chose mais pour récupérer les valeurs puis a nouveau les envoyer etc

Le fabriquant m'a envoyé un MP pour me dire qu'ils étaient en train de développer une nouvelle librairie spécialement orientée Arduino/SerialSofware. Ca va donc changer dans peu de temps ... il va donc falloir qu'on modifie encore nos codes.

Merci en tout cas de m'avoir envoyé les vôtres. Je vais étudier ça très attentivement.
A charge de revanche XD

bye bye

Pour tous les possesseurs d’écran 4D systems sous Visi-Genie, les développeurs viennent (enfin) de sortir la nouvelle libraire genieArduino.

Donc pour conclure ce fil de discussion : ça ne servait a rien qu'on s'acharne puisque la librairie était boiteuse :smiley: