Lecture d'une trame transmise cycliquement

Bonjour,

Dans le cadre d’un projet, je dois venir lire et interpréter une trame “TIC” d’un compteur linky sur arduino.

La trame en question est une série de bit émise à 1200 bauds de façon cyclique avec, entre chaque trame un délai de quelques millisecondes (~30ms).

Il faut aussi savoir qu’entre chaque trame un état logique “1” est présent à l’entrée du port, donc pour résumé le port que j’aimerais lire fait quelque chose comme :

111111…11111 [Trame à lire] 111111…1111 [Trame à lire] 11111…1111 etc…

sachant que [Trame à lire] commence systématique par le caractère ASCII stx (0x02) et fini systématiquement par le caractère ASCII etx (0x03).

De plus la partie entre chaque trame avec que des “1” logique ne m’intéresse pas et je ne veux pas l’afficher sur le moniteur série de l’arduino.

Je cherche donc un moyen de détecter le “stx” et “etx” pour isoler la trame en question et n’afficher qu’elle sans les 1111…11111 entre chacune d’elles.

Actuellement, j’ai un programme qui permet d’afficher tout ce qui est présent sur le port en question (avec les 1), mais j’ai beau réfléchir je ne trouve pas de moyen d’isoler la partie entre stx et etx, si vous avez une idée, n’hésitez pas.

Voici mon programme pour l’instant :
(Je précise que je suis débutant en arduino)

#define startFrame 0x02
#define endFrame 0x03

void setup() {

  Serial.begin(1200);
  pinMode(8, INPUT);

}

void loop() {

  boolean val = digitalRead(8);
  Serial.print(val);
}

Je met également ce que j’obtiens sur le moniteur série en pièce jointe.

Merci d’avance.

Ce ne sont pas les sujets LINKY qui manquent sur le WEB.

Si c'est du serial 1200 baud pourquoi lire ça avec digitalRead() ?
Un SoftwareSerial + read()

https://www.domotique-info.fr/2014/05/recuperer-teleinformation-arduino/

Bonsoir,

Votre code ne fait qu’indiquer en boucle l’état d’une broche en l’affichant sur le port série.

Ne confondez pas niveau logique 1, qui correspond à un état haut sur une broche avec le code ASCII du caractère ‘1’.

Pour décoder facilement une trame série, il serait préférable d’utiliser l’entrée d’une interface série.

Vous utilisez actuellement une interface matériel pour visualiser le niveau de la broche, mais vous pouvez aussi en émuler une logiciellement afin de continuer à scruter vos variables.

Cas n°1 (facile)
tes paquets de “1” font un multiple de 8 bits.
Dans ce cas tu reçois des octets, 0xFF, 0xFF, 0xFF… (=8 bits à 1). Tu les ignores tous.
Et d’un coup tu reçois 0x02. C’est le début de la trame. Tu notes les octets jusqu’à lire 0x03, et tu te remets en attente de 0x02.
Pour gérer cela, il faut une petite machine à état. Tu as 2 états :

  • en Attente (tu reçois des 111111)
  • en Ecoute (tu as reçu 0x02, mais pas encore 0x03)
    Tu crées une variable qui contient l’état (0 ou 1, ou -1 et +1, ou vrai ou faux, peu importe).
    Au départ tu es en Attente (comme ça si tu chopes la 1ère trame par le milieu, tu la mets à la poubelle).
    Quand tu reçois 0x02, tu passe à l’état Ecoute. Pour 0x03, tu repasses en Attente.

Cas n°2 (moins facile…)
Le nombre de bits entre deux trames est quelconque (pas forcément multiple de 8 )
Il faut rajouter une couche avant ce que j’ai décrit précédement.
Tu démarres en état Attente. Tu reçois des octets.
Si l’octet vaut 0xFF, tu le jettes. C’est du remplissage.
Sinon, tu le décales vers la gauche ( opérateur << ) jusqu’à ce que le bit de poids fort soit un 0. Autrement dit, tu vires tous les bits à 1 au gauche. Tu notes de combien de bits tu as shifté (de 1 à 7).
Si par exemple le 1er octet significatif contenait 5 bits à 1 à gauche (11111xyz), après l’avoir décalé 5 fois il vaut xyz00000.
Puis tu attends l’octet suivant. Il faut prendre les 5 bits de poids fort de ce nouvel octet et les injecter dans xyz00000 à la place de 5 0 finaux. On fait ça avec les opérateurs de décalage >> et >> ainsi que les “et” & et “ou” | logiques.
Et tu continues comme ça, octet par octet, à détricoter les octets entrants (les valeurs sont “à cheval” sur 2 octets"), jusqu’à voir passer ETX.

Ca s’appele jouer au bit, la plupart des programmeurs détestent ça :slight_smile:

biggil:
tes paquets de "1" font un multiple de 8 bits.
Le nombre de bits entre deux trames est quelconque (pas forcément multiple de 8 )

A mon avis l'état 1 entre chaque trame est un état 1 continu, l'état normal de repos d'une ligne RX.
Donc à ne pas considérer comme bit.

SoftwareSerial.available() retournera 0 dans ce cas.

Oui, il a un truc que je n'ai pas dit.
Tu ne vas pas lire directement la broche RX par digitalRead().
C'est beaucoup trop compliqué.
Tu vas utiliser un objet spécialisé, du genre Serial ou SoftwareSerial.
Cet objet s'occupe de tout (recevoir les bits un par un sous tes pieds, sans que tu t'en occupes).

Cet objet ne te fournit que des octets entiers (8bits). Jamais il ne dit "tiens, voilà 3 bits qui viennent d'arriver". C'est pour cela que dans mon message ci-avant, je parle uniquement de revoir des octets entiers.

[Edit]On ne connait pas le protocole bas-niveau de cette LNS; mais classiquement un octet commence par un bit de start, des bits de data + autres éventuellement (parité, stop).
Donc lorsque la ligne est maintenue à un niveau constant, le driver Série ne voit ... rien.
Pas de bit de start détecté -> pas d'échantillonage de la ligne -> pas d'octet reçu.

Oui c’est bien comme cela que je le comprends.

Quand tu parles de bits à 1 reçus entre deux trames, c’est une erreur. Il s’agit simplement d’un état 1 permanent. Il n’y a donc rien a faire.

Le cas dont tu parles “Cas n°2 (moins facile…)” n’existe pas.
On ne recevra jamais 0xff entre deux trames. Pas besoin de toute ces manipulations de décalage.

Merci beaucoup pour vos réponses, j'ai utilisé la library SoftwareSerial comme suggérée et ça fonctionne parfaitement.