Problème de compatibilité librairie Visie-Genie et port Serial

Bonjour

De retour parmi vous après de longs mois…Suite à ce qu’un certain Alien me fasse découvrir une nouvelle version encore plus simple des applicatifs de 4Dsystems. Le mode Visi-Genie.

Je me suis dit là, c’est pour moi. Du coup, j’ai ressorti ma vieille dalle µLCD32PT qui dormait au fond d’un tiroir. Et l’ai finalement branchée.
Dans ce mode de développement (Visie-Genie) il existe une librairie Arduino spécifique : GitHub - 4dsystems/ViSi-Genie-Arduino-Library: ViSi-Genie - Arduino Library
J’ai installé celle-ci dans le répertoire des librairies. Mais j’ai un conflit entre cette librairie et la gestion du port série.
Sur un sketch faisant appel à « Serial » (dans le setup par Serial.begin(38400); ou une instruction Serial.println(); dans le loop) l’inclusion de la lib #include <genieArduino.h> génère un défaut de compilation.

core.a(HardwareSerial.cpp.o): In function __vector_18': D:\Session Franck\Logiciels spécifiques\Arduino\arduino-1.0.4\hardware\arduino\cores\arduino/HardwareSerial.cpp:116: multiple definition of __vector_18’
genieArduino\genieArduino.cpp.o:D:\Session Franck\Logiciels spécifiques\Arduino\arduino-1.0.4\libraries\genieArduino/genieArduino.cpp:110: first defined here

En cherchant un peu, je constate que c’est l’utilisation du port USART0 qui est redondante.
On le trouve dans la lid Visie-genie en ligne 110 :

/*
 * USART_RX_vect:
 *	Character RX interrupt vector
 *	This is the heart of the system - we use it to read in data from
 *	the display and save it for later reading.
 *********************************************************************************
 */

#if !defined (USART0_RX_vect)
#	define USART0_RX_vect USART_RX_vect
#endif

ISR(USART0_RX_vect)
{
  uint8_t data ;
  static uint8_t cmd, object, index, msb, lsb ;
  static uint8_t checksum ;
  static uint8_t state = 0 ;
  struct genieReplyStruct *reply ;
  int next ;

  data = UDR0 ;

Et dans le fichier HardwareSerial de l’IDE Arduino.

}

#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
// do nothing - on the 32u4 the first USART is USART1
#else
#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \
    !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \
	!defined(SIG_UART_RECV)
  #error "Don't know what the Data Received vector is called for the first UART"
#else
  void serialEvent() __attribute__((weak));
  void serialEvent() {}
  #define serialEvent_implemented
#if defined(USART_RX_vect)

(J’ai testé dans toutes les versions 1.0.x, c’est idem)

C’est là que je suis bloqué. Y a-t-il une solution ?

Merci pour votre aide
Franck

Bonjour,

C’est là que je suis bloqué. Y a-t-il une solution ?

Je n'en vois qu'une : ne pas utiliser Serial dans ton code.

La librairie Genie semble englober tout ce qui est lié au port série : https://github.com/4dsystems/ViSi-Genie-Arduino-Demo-Calculator/blob/master/calculator/calculator.pde

Ah oui, effectivement. D'autant plus, qu'en ayant avancé dans la compréhension du système de dialogue, je me suis rendu compte que ce sont les pin 0(Rx) et 1(Tx) qui sont employés, et non plus du port série softserial comme dans les précédentes applications. Donc c'est utilisation de la dalle 4D, OU du terminal, OU chargement du sketch. :0

Merci

Bubule: Donc c'est utilisation de la dalle 4D, OU du terminal, OU chargement du sketch. :0

On peut pas tout avoir dans la vie ;)

Comme évoqué plus haut, j’ai pu ressortir ma dalle 32 ‘’ 4D Systems de son tiroir.

Je programme la dalle avec son nouvel outil de programmation, le mode Visi-Genie de l’IDE Workshop4 : http://www.4dsystems.com.au/new/product/10/120/Development/4D_Workshop_4_IDE/

Afin que ma UNO puisse dialoguer avec celle-ci, j’utilise la librairie Visi-Genie Arduino library : GitHub - 4dsystems/ViSi-Genie-Arduino-Library: ViSi-Genie - Arduino Library

Si ces modes d’utilisation semblent simples, et si les quelques exemples et vidéos qui traînent sur le net (j’en vois 2) nous montrent des applications réussies, le développement de la mienne, qui est une extension d’un système aujourd’hui en place, et qui fonctionne 24h/24 depuis de nombreux mois, me pose problème(s).
Les documentations sont encore rares, et la recherche des causes de plantages m’est bien compliquée.

Mon système est actuellement composé de deux cartes Arduino qui dialoguent entre elles par liaison série softSerial.

  • Une carte Mega qui gère tous les automatismes, et envoi toutes les secondes quelques valeurs à la Uno.
  • Une carte Uno qui effectue l’envoi des valeurs reçues (précédemment sur écran PC via la liaison USB, prochainement sur le µLCD32 de 4D Systems).
    Cette Uno effectue également quelques vérifications
  • Bonne réception des valeurs de la Mega qui indique qu’elle est toujours en fonction. (Chien de garde)
  • Mesures redondantes de paramètres

Tout cela ne s’est pas fait sans les petits problèmes de développements habituels (pour moi). Vous l’avez deviné, je ne suis pas un dieu de la programmation.
J’espère que vous accepterez de m’aider à rechercher les causes aux problèmes que je rencontre et m’aider à trouver la (les) solution(s).

Premier problème rencontré (et résolu au dessus) : Avec la librairie VisiGenie-Arduino, le dialogue entre la Uno et le µLCD s’effectue obligatoirement par la liaison série « hard » par les pins 0(Rx) et 1(Tx). Donc erreur à la compilation si on souhaite utiliser ce port par ailleurs (en utilisant l’instruction print() ou Serial.begin() par exemple.)

L’envoi de valeurs à l’afficheur s’effectue par l’instruction genieWriteObj (type d’objet, N° objet, variable à envoyer). Celles-ci sont prises en compte, et ne sont affichées que si le formulaire est en cours. Pour ma part, j’envoi une liste de toutes les valeurs à afficher cinq fois par seconde. Jusque là, tout semble bien fonctionner.

Second problème, que je n’arrive pas à résoudre et pour lequel je fais appel à vos lumières :
Une action sur l’écran tactile, comme l’appui sur un bouton, est envoyée à la Uno, qui la lit sous la forme variable Arduino = genieReadObj (type objet, N° objet)
Cette instruction fait planter la Uno en quelques secondes.
Il semble qu’un buffer se remplisse et bloque la carte.
La dalle et la Uno fonctionnent correctement tant qu’aucune instruction genieReadOgj() n’est écrite dans le sketch. L’envoi des données reçues par la Softserial (Serial45) au µLCD se fait correctement au travers de la Uno.
Le sketch fonctionne également correctement avec les instructions genieReadOgj(), tant que la Uno ne reçoit pas de donnée de la Softeserial. L’appui sur un bouton (de la tactile) qui incrémente ou décrémente une valeur fonctionne. Quelques secondes après avoir branché la liaison Uno/Mega, la Uno se plante. Le transfert des variables de la Mega vers le µLCD s’effectue correctement, mais seulement pendant quelques secondes. (Entre 10 et 15’’).

Je suspecte une incompatibilité entre l’utilisation des 2 librairie Softserial et VisiGenieArduino. Mais la résolution de ce problème dépasse mes compétences.

Le sketch, sous V1.0.4.

/* PROGRAMME TEST GESTION DES SECURITES ET LIAISON AFFICHEUR
*/

// Inclusion des librairies

#include <genieArduino.h>
#include <SoftwareSerial.h>

#include <stdio.h>
#include <stdint.h>
#include <ctype.h>

// Déclaration des ports série
  SoftwareSerial Serial45(4,5);  // Port série pour liaison Mega / Uno
 
  

// Declaration des entrees
 
// Declaration des variables 
  
  int plus;           // Variable +
  int moins;        // Variable -
  int valeur = 0;  // Valeur modifiée par + ou -
  
  
  
 // Déclaration des variables et constantes horloge
  unsigned long refTemps;         // Mémoire de l'horloge millis pour horloge principale
  unsigned long refTemps2 = 0; // Mémoire 2 de l'horloge millis pour horloge 200ms
  
  int topsec = 0;                 // Impulsion topsec toutes les secondes 
  int top02s = 0;                 // Impulsion top02s toutes les 200 millisecondes 
  


 //Tableaux de variables
  long tableauRX[10] = {0};      // Déclare le tableau tampon de réception de la liaison série
  long tableauDonnees[30] = {0}; // Déclare le tableau à 30 lignes (3 réceptions de 10 lignes)
  
  
 // Valeurs du tableau de variables qui doivent être reçues de la carte Mega
  double pH = 0.00;              // recoit la mesure de pH de la Mega
  unsigned long milli = 0;     // recoit la valeur milli() de la Mega

 // Variables (mesures Uno pour redondance)
  double pHsecu =  8.30;     // Mesure pH Uno
 
  
  

 
#define READ_OBJ 0x00
#define WRITE_OBJ 0x01
#define REPORT_OBJ 0x05
#define REPORT_EVENT 0x07

 
 
 
 
 
void setup() {
  

  Serial45.begin(38400);         // Initialise la liaison série soft 45  
  genieSetup (38400);            // Initialise la liaison µLCD
    
  pinMode (4, INPUT);            // Déclaration du pin 4 en RX
  pinMode (5, OUTPUT);           // Déclaration du pin 5 en TX

  digitalWrite (4, HIGH);        // Activation du pullup de l'entrée 4 (RX)
  digitalWrite (5, HIGH);        // Activation du pullup de l'entrée 5 (TX)
    
  delay (3000);
  
} //FIN de SETUP





// FONCTION LOOP
void loop() {      
    
   // HORLOGES 
      if (millis() >= refTemps){
         refTemps += 999;
         topsec = 1;          // Monte le bit topsec toutes les secondes
          }
            
      if (millis() >= refTemps2){
         refTemps2 += 200;
         top02s = 1;          // Monte le bit top02s toutes les 200 millisecondes
         }
         
         
  // ENREGISTREMENT VARIABLES EXTERNES MEGA       
  
  if (Serial45.available()) {                       // Sur réception de données sur la liaison série soft (45)
      if (tableauRX[0] = recevLong()) {          
          for ( int rx = 1 ; rx < 10 ; rx++ ){      // Enregistre les 10 variables dans un tableau
            tableauRX[rx] = recevLong();            // en faisant appel à la fonction "recevLong"
            delay(1);  }
         }
     }
     
   if (tableauRX [0] == 111111111) {                // Si réception correcte des 10 premières valeurs ( 1ère var du tableau = 111111111)
       for (int rx1 = 0 ; rx1 < 10 ; rx1++ ){   
         tableauDonnees[rx1] = tableauRX[rx1] ;     // Transfert les données dans les 10 premières variables du tableau de données
       }
     }
    
     else Serial45.flush() ;
    
     
   // Transfert des variables du tableau vers chaque variable
     long var0 =               tableauDonnees[0] ;    // = 111111111 si 10 premières valeurs
          milli =              tableauDonnees[1] ;
     long heureExt  =          tableauDonnees[2] ;
     long minuteExt =          tableauDonnees[3] ;
     long secondeExt =         tableauDonnees[4] ;
     long posServo1 =          tableauDonnees[6] ;
     long posServo2 =          tableauDonnees[7] ;
     long AttenteNourrissage = tableauDonnees[8] ;
     long brassageAux =        tableauDonnees[9] ;
    
    
    
    
  // AFFICHAGES
 
     if (top02s && !Serial45.available()) {  
       
       genieWriteObj (GENIE_OBJ_LED_DIGITS, 0, pH);
       genieWriteObj (GENIE_OBJ_LED_DIGITS, 1, pHsecu*100);
       genieWriteObj (GENIE_OBJ_LED_DIGITS, 2, pH);
       genieWriteObj (GENIE_OBJ_LED_DIGITS, 4, valeur);   // Valeur modifiée par boutons +/-
       genieWriteObj (GENIE_OBJ_CUSTOM_DIGITS, 0, heureExt);
       genieWriteObj (GENIE_OBJ_CUSTOM_DIGITS, 1, minuteExt);
       genieWriteObj (GENIE_OBJ_CUSTOM_DIGITS, 2, secondeExt);
       genieWriteObj (GENIE_OBJ_COOL_GAUGE, 0, posServo1);
       genieWriteObj (GENIE_OBJ_COOL_GAUGE, 1, posServo2);
   
    delay(25);
     
       plus = genieReadObj (GENIE_OBJ_WINBUTTON, 11);
       moins = genieReadObj (GENIE_OBJ_WINBUTTON, 12);
     }
     

     if (plus && valeur <=999 ) {valeur ++;}   // Incrémente Valeur
     if (moins && valeur >=1) {valeur--;}        // Décrémente Valeur
    

//  RAZ
        plus = 0;
        moins = 0;    
     
   topsec = 0; 
   top02s = 0;

   
     
} // FIN de LOOP



// FONCTION DECODAGE RECEPTION OCTETS SUR LIAISON SERIE
  long recevLong() {    
    while (Serial45.available() < 4 ); 
      long recu = ((unsigned long)Serial45.read() | ((unsigned long)Serial45.read() << 8 ) | ((unsigned long)Serial45.read() << 16) | ((unsigned long)Serial45.read() << 24));
    return (recu); 
        
 }

Franck

J'ai qu'un simple écran sans tactile donc je ne pourrai pas t'aider sur le 2ème problème :~

Le plus simple est de contacter le support 4D Systems.

L’adresse de leur forum est http://4d.websitetoolbox.com/

Bonjour,

Je vous suggère de ne pas utiliser la librairie VisiGenie-Arduino mais d'étudier les deux exemples disponibles à la page http://www.4dsystems.com.au/appnotes/

4D-AN-P4010 ViSi-Genie Connection to a Host with Red-Green-Blue LED Control Rev 1.1 4D-AN-P4014 ViSi-Genie Connection to a PIC32 Host with Security Gate Keeper Rev 1.0

Je vous conseille de connecter l'écran sur un port SoftwareSerial pour éviter tout problème lors du chargement du programme vers la carte Arduino.

La gestion du dialogue avec l'écran est très simple à mettre en œuvre. chipKIT permet de gérer les commandes directement avec des uint64_t, ce que Arduino ne permet pas.

Les deux exemples offrent les fonctions de lecture et d'écriture vers l'écran.

En utilisant la méthode décrites dans les documents PDF, vous pourrez établir la liste des séquences, ordres, commandes et réponses.

Le reste relève de l'intégration avec votre code.

Bien cordialement,

Aie Aie Aie !! =( =(

Si les dieux du programme jettent l’éponge. Çà ne sent pô bon du tout !

Merci en tous cas de vous être penché sur mon problème, même si l’issue n’est pas positive. :~

Je vais retourner faire un tour du coté du forum 4D, histoire de leur remonter le problème de compatibilité des librairies. On ne sait jamais, mais vu l’enthousiasme qu’ils ont montré à me répondre sur le sujet… :% ]:D En attendant, je vais tenter de redévelopper en mode VisiGenie par le Soft Serial comme dans l’exemple 4D AN P4010 (Led RVB). Je devrais être capable de reproduire ce principe. Je vais encore perdre des cheveux... :roll_eyes:

Merci Skywodd et Avenue33

Franck

Bonjour

De retour avec quelques cheveux en moins. (Va plus rester grand-chose) :disappointed_relieved:

Comme proposé par Avenue33, j’ai donc supprimé la librairie VisiGenie pour re-développer mon sketch selon le principe de l’exemple 4D-AN-P4010 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 Et donc en utilisant la librairie Softserial pour dialoguer également avec la dalle. Sans être allé jusqu’au bout, j’ai commencé par vouloir faire afficher par la Uno les valeurs issues de la Mega. Les problèmes commencent, car la librairie SoftSerial sait traiter plusieurs ports, mais pas de manière simultanée ou autonome. Cela nécessite que l’on commande l’écoute sur le bon port (avec Serial.listen()). Et comme la Mega envoie ses données de manière temporisée (et la dalle de manière aléatoire en fonction de l’appui sur les touche). Je ne sais pas où positionner correctement l’écoute. Je ne vois pour le moment qu’un seul moyen : Sur top Uno, envoi des données (modifiables par le biais de la dalle) à la Mega. Et écoute du port SerialMega Après réception des données, la Mega envoie ses valeurs. A la réception des valeurs, écoute du port SerialDalle et envoi des données à la dalle dans la foulée, et attente jusqu’à nouveau top Uno.

Avez-vous une idée du temps que peux prendre le transfert des données de la Mega vers la Uno ? Par flux de 15 long selon le principe que nous avions développé ici ? http://forum.arduino.cc/index.php?topic=85310.msg652230#msg652230 De plus, comme j’ai plus de 20 variables à transférer depuis la Mega, je suis obligé de les envoyer en plusieurs flux. (Au-delà de 15 long par flux, y’a plantage de la Uno, ou interruption trop longue sur la Mega, ce qui provoque des problèmes avec les autres librairies comme « servo »). Faudrait pas que cela prenne trop de temps, si je veux pouvoir écouter suffisamment longtemps l’arrivée possible de commandes issues de la dalle tactile…

D’autres idées ?

Port série matériel pour la connexion avec l'autre carte Port série SoftwareSerial pour l'écran.

J'ai rien compris perso :sweat_smile: Fait nous une petite récap des communications mega / uno / écran.

Je crois comprendre que tu fait ça actuellement : PC - usb/Serial - mega - softserial/softserial - UNO - Serial - écran

J'ai bon ?

Pfffff c’est plus c’que c’était les dieux dl’a prog :D

Avenue33 B’en si je fais çà, je perd la liberté de l’USB et son potentiel de déboguage par le terminal. Bon, je peux toujours réinjecter un soft sur la UNO le moment venu pour lire les valeurs reçues de la Méga, mébon.

Spécialement pour Skywood j’vais essayer de faire court (Edit : j’ai pô pu !) et compréhensible (Edit : faudra me dire).

L’état actuel : Depuis plus d’un an, après avoir développé la liaison série entre les deux cartes, comme évoqué dans le lien précédent, j’ai donc une Mega qui gère tous les automatismes d’un aquarium récifal. Cette Mega envoie toutes les secondes, via un port Serial1, une liste de 15 valeurs « long » La Uno reçoit ces valeurs via un port SoftSerial, et les stocke en tableau. Toutes les secondes, sur top horloge (Uno), elle envoie les valeurs du tableau mises en forme, sur le port USB. Je connecte mon PC à la UNO pour lire ces valeurs lorsque j’ai besoin de lire les paramètres du bac (étalonnage de sondes par exemple).

C’est peu pratique, et la modification de consignes s’effectue en raccordant le PC à la Mega, et en modifiant les valeurs dans la déclaration des variables. Pourquoi 2 cartes ? Parce que par sécurité, j’ai besoin de redondance. La Uno effectue également ses propres mesures et verrouille certaines sorties de la Mega sur dépassement de seuils critiques. Elle effectue également un Reset de la Mega si elle ne reçoit plus d’info sur le Softserial au bout de 10 secondes.

Le besoin : Dialoguer en direct avec la UNO sans raccorder le PC. Et pouvoir également modifier les consignes qui sont stockées dans la Mega. (Ensuite, faudra sauver ces nouvelles consignes en EEPROM. Mais chaque chose en son temps).

Les softs sont à adapter en fonction, sachant que : - Des infos peuvent survenir à tout moment de la tactile (appui touche écran). Mais on peut accepter que celle-ci ne soit pas immédiatement réactive. Les touches sont des "+" ou "–" ou "Marche/Arret" (pour le moment). - L’horloge (hh/mn/ss) est dans la MEGA et j’aurais souhaité mettre à jour l’affichage sur la dalle tactile au moins toutes les secondes. - Les ports SoftSerial ne peuvent être écoutés en même temps.

Quelques nouvelles de mes avancées :

A présent, le système fonctionne. Malgré que je continue le développement. Pour ceux qui souhaiteraient développer un projet similaire, voici comment j’ai procédé :

Les cartes Arduino Uno et Mega dialoguent entre elles par liaison série grâce à la librairie EasyTransfer. (Car les fonctions de transfert de ‘long’ que nous avions développées précédemment ne fonctionnaient plus en bidirectionnel). - SoftSerial pour la Uno, et Serial 1 pour la Mega, car la librairie EasyTransfer sous softSerial effectue une interruption qui gène le fonctionnement de la librairie ‘Servo’. (Les servos sont lâchés pendant que le transfert de données s’effectue).

  • Le µLCD est également raccordé sur un port SoftSerial sur la UNO.

Comme la librairie Softserial ne sait traiter qu’un port à la fois, j’utilise la procédure suivante : Sur top horloge (toutes les secondes) je positionne le port softserial vers la Mega (SerialVersMega.listen()). La Uno envoie une liste de données à la Mega. Dont la dernière variable est une valeur ‘signal' d’envoi (1111111 par exemple).

Sur réception de cette valeur, la Mega, après un petit délai (20ms), retourne sa propre liste de valeurs à la Mega, et remet à 0 la variable 'signal' qui était passée à 1111111.

Une fois cette liste de valeurs enregistrée dans la Uno, celle-ci positionne l'écoute du port sur l’afficheur (SerialLCD.listen()), et met à jour l’affichage, puis attend le prochain top horloge(écoute du µLCD) Cette écoute dure plus de 90% du temps (la durée de transfert UNO>MEGA>UNO>LCD dure environ 70ms)

Sur réception d’une touche µLCD, la liste est immédiatement envoyée à la Mega, comme un top horloge.

Je finalise le projet, et tenterais de vous donner les morceaux de codes une fois l’ensemble définitivement validé.

Fabinou30:

Bubule:
J’en avais parlé ici : http://forum.arduino.cc/index.php?topic=165968.msg1258043#msg1258043

Et pour t’éviter trop de recherches : EasyTransfer Arduino Library « The Mind of Bill Porter

Désolé de t’embêter encore mais côté branchement ça donne quoi ??
Car sur le site en anglais je ne vois pas d’indication sauf un digitalWrite(13, HIGH / LOW) je pense qu’il faut plutôt brancher sur les Pins série donc plutôt comme ça ?? arduino UNO → arduino MEGA
tx → tx1 (Comme ça, en direct, sans résistance)
rx → rx1 (Comme ça, en direct, sans résistance)
gnd → gnd (Devinez quoi … Comme ça, en direct, sans résistance)

Je n’éssayes pas ce montage, trop peur de faire cramer les 2 arduinos ensemble donc si tu peux juste me dire le cablage par MP si ça t’embête de parler de ça dans ton sujet … Fais le STP !!

Oui, le branchement s’effectue en direct, sans composants externes. RX > TX ; TX > RX ; GND > GND
Il te faut choisir les bons ports de sortie en fonction des librairies Easytransfer que tu charges (Soft ou hard). Sur la UNO, je te conseille d’utiliser la soft pour laisser le port hard 0/1 libre pour le monitoring.

Franck