Branchement sur port série

Bonjour,

nous (association Fort de Mutzig) mettons au point une maquette (2m sur 2m) qui représente la colline sur laquelle est construite le Fort de Mutzig (20 km à l'ouest de Strasbourg).
Après retards, refonte du projet, etc, nous en sommes à 50 circuits différents (!), pilotés par un Arduino Mega.
Architecture générale :

  • un écran tactile Nextion, relié à un Arduino Mega sur le port série 1.
  • l'Arduino Mega qui commande un bus I2C
  • un bus I2C sur lequel sont branchés 7 décodeurs qui pilotent 7 à 8 LED chacun (par exemple, en rouge les canons de 155mm, en orange ceux de 105mm, en bleu les observatoires etc).

Actuellement, ça fonctionne avec l'écran Nextion qui commande l'allumage de l'artillerie, des observatoires etc. C'est très souple d'emploi et configurable à volonté. De plus, lorsqu'on ne touche pas l'écran tactile pendant 30 secondes la routine "Construction des infrastructures" se lance : depuis 1893 jusqu'à 1916 les LED s'allument, chaque seconde représente une année, puis on éteint tout et on recommence.

Une idée est arrivée : et si on laissait se dérouler le programme de "Construction" sans l'écran ? En rajoutant juste un inter sur la ligne 5V d'alimentation de l'écran ou en démontant carrément l'écran.
Hélas, ça ne marche pas aussi facilement que prévu.
En début de loop(), j'interroge l'écran branché sur le port série 1 :
if (Serial1.available()) {....}
Lorsqu'il n'y a pas d'écran branché, le programme coince, bloque et me perturbe sur cette instruction !

Y a-t-il une solution de contournement ?

Bonjour.

Pour vous aider, il nous faut le maximum d'informations utiles.

Ici, le code est plus que nécessaire.

Au lieu de mettre l’inter sur l’alimentation mettez le sur une pin et si la pin est active c’est que vous voulez le mode auto sinon le mode avec l’écran

Je n'ai rien d'extraordinaire

 byte Message[7];
  byte i;
  boolean msg = false;
  if (Serial1.available()) 
  {
    for (i = 0; i < 7; i++) 
    {
      Message[i] = Serial1.read();
    }
    NumPage     = Message[1];
    NumTouche   = Message[2];
    AppRelache  = Message[3];
    msg = true;
  }

La version d'essai avec des Serial.print pour moniteur série montre que ça cale bien sur Serial1.available cad quand on regarde sur le port série 1 quand rien n'est branché dessus.

Oui, mais ça m'ennuie un peu de mettre un inter de plus.
Si on ne veut pas que les visiteurs jouent avec la maquette en tapotant l'écran, c'est la décision du guide de service de basculer l'inter qui coupe l'alim de l'écran.
Il faudrait donc que je ramène le 5V alim écran après l'inter vers une pin libre, en la tirant à la masse avec une résistance. Et je devrais ajouter le test de cette pin avant d'aller à la lecture du port série.

OK je comprends que vous ne voulez pas modifier plus que cela le hardware

il vous faut trouver un moyen non bloquant de voir si l’écran est alimenté. Je n’utilise pas les écrans nextion, peut être il y a moyen d’envoyer un message sur le port série (par exemple le N° de version ou de série ou quelque chose comme cela) et attendre une réponse. Si la réponse ne vient pas au bout d’une seconde par exemple alors c’est que l’écran est éteint (ou endommagé).

C'est une mauvaise idée de couper l'alimentation de l'écran. Le Tx de l'Arduino envoie une tension sur le Rx du Nextion. Cette tension n'est pas suffisamment élevée pour alimenter correctement l'écran mais peut néanmoins le mettre dans un état indéterminé est placer la ligne Tx de l'écran à un niveau qui peut perturber l'Arduino.

Je suggérerais plutôt de :

  • couper la ligne Tx du Nextion (ou couper l'alimentation du Nextion ET la ligne Tx ou le supprimer carrément) en prenant la précaution de placer une résistance entre Rx Arduino et GND.
  • Au démarrage, placer un delay() pour laisser le temps au Nextion d'être opérationnel s'il est présent (quelques secondes je suppose).
  • Lire l'état de la ligne Rx de l'Arduino:
    • si la ligne est à LOW, alors il n'y a pas d'écran
    • si la ligne est à HIGH, alors il y a un écran de connecté

J'aimerais mieux connaître les finesses de la fonction Serial.read()

A priori (merci de contrôler ce que je dis), on utilise un protocole série via un UART (Universal Asynchronous Receiver Transmitter).
Le Tx de l'écran envoie en permanence un +5V sur le Rx de l'Arduino ; lorsqu'il a un octet à transmettre, il tombe la ligne à 0V puis envoie l'octet, bit de poids faible en tête.
En règle générale, il y a toujours +5V sur Rx de l'Arduino, et quand quelques milliers de fois par seconde on passe sur "Serial1.available", on continue dans le programme. parce qu'il n'y a pas de commande depuis l'écran.
En revanche, s'il n'y a pas de signal sur Rx, l'UART pense que c'est un bit de start qui se prolonge, et l'instruction de lecture patauge dans la semoule en attendant quelque chose de concret. On ne peut pas utiliser cette fonction pour tester la présence d'un écran.

Idée diabolique que je vais tester : la borne Rx du serial1 de l'Arduino Mega est sur la pin 19 (Tx sur 18). Si dans le setup je déclarais :
pinMode (19, INPUT_PULLUP) ;
alors lorsqu'il n'y a pas d'écran il y aurait par magie toujours un +5V sur Rx
et s'il y a un écran, il est possible que l'UART de l'écran arrive à transmettre quand même ses 0V.

Demain vendredi 26, je teste cette idée : est-ce raisonnable ? Quels sont les risques ?

dans la doc ils disent

MCU sending to Nextion

1. MCU sends command. ie: wept 30,20ÿÿÿ or addt 1,0,320ÿÿÿ (le ÿ c'est l'octet 0xFF)
2. Nextion requires ~5ms to prepare for transparent mode data transfer
3. Nextion sends “Ready” 0xFE 0xFF 0xFF 0xFF Return Data (see 7.32)

➜ je ferais cela pour tester la présence de l'écran. l'envoi de la commande est rapide, si la réponse "Ready" (0xFE 0xFF 0xFF 0xFF) ne revient pas dans les 100ms qui suivent c'est que l'écran n'est pas là ou ne fonctionne pas

C'est ce que je fais : je récupère 7 octets du Nextion (hélas uniquement) lorsque l'écran Nextion est là (!).
Mais clairement, si j'envoie cette commande au Nextion, elle devrait partir quel que soit la cas (écran ou pas) mais je me retrouverai coincé comme maintenant à attendre que l'écran réponde.
J'ai bien conscience qu'il manque (ou que je ne sais pas me servir) d'un timeout dans la fonction Serial.read(). Je n'ai probablement pas assez cherché sur Internet mais je n'ai trouvé personne qui évoque le risque de coupure physique du lien série...
Et comme ce outil est destiné à des gens qui ne lisent pas forcément le mode d'emploi, je dois être prudent.

Du coup, je vais tenter 2 idées :

  1. Je vais essayer simplement de déclarer dans le setup pinMode (19, INPUT_PULLUP) ;
  2. Sinon, je rajoute dans le setup pinMode (19, INPUT) ; et je teste à chaque fois si la pin 19 est à l'état haut avant de me hasarder à lire l'UART par un Serial1.read() ;

J'espère juste que cette intervention directe sur la pin Rx ne froissera pas les fonctions Serial.available() et sa copine Serial.read()

Read nest pas bloquant donc vous essayez de lire pendant un certain temps et si vous n’avez pas la réponse alors c’est que l’écran n’est pas là ➜ en gros un while avec millis()

Voila, mon problème est résolu ! Je viens de tester la modification de logiciel, sans toucher au hard.
J'ai simplement rajouté dans le setup :
pinMode (19, INPUT_PULLUP) ;
Ça amène bien une résistance de pullup sur cette borne. Cette borne au +5V est analogue à cette borne avec un écran à port série "qui reste muet".
Lorsque l'écran est présent, il arrive à envoyer ses données, cad le bit de start à 0V arrive à passer outre le 5V permanent. L'écran et son fonctionnement ne sont pas perturbés, l'UART en charge de la gestion du port série n'y voit que du feu.
Et donc mon programme réagit comme je le souhaite maintenant.
La partie délicate du projet se termine, il ne me reste maintenant plus qu'à traduire en allemand la page d'accueil, et à créer d'autres pages d'écran pour faire d'autre types de présentation.
Nous nous félicitons de ce choix d'utilisation d'un écran tactile et d'un contrôle par un Arduino pour la souplesse que ça procure.
Nous mettrons cette maquette en service fin 2023.
Pensez à venir nous voir. http://www.fort-mutzig.eu

Merci à tous les intervenants qui m'ont guidé et inspiré mes réflexions !

Bravo

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.