Skip to content

Artilect-FabTronic/Arduino-Machine-A-Etats

Repository files navigation

Arduino-Machine-A-Etats

Ce projet collaboratif a pour but de comprendre le fonctionnement et l'implementation des machines à états pour structurer un programme embarqué.

Nous allons pour cela mettre en oeuvre une partie du protocol Modbus qui peut être composé soit de données brut "RTU", soit de données textes "ASCII".

Format de message Modbus ASCII

Le format des messages Modbus ASCII comprend un caractère de début qui est un deux-points ':' et la fin du message est définie par la combinaison d'un retour à la ligne et d'un saut de ligne (CR LF). Ce type de protocole permet de faire varier le temps de transmission de chaque donnée du message, comme lorsque celui-ci est entrée à la main dans un terminal.

Voici une description complète d'un message Modbus ASCII :

Start Address Function Data LRC End
':' 2 Chars 2 Chars N Chars 2 Chars CR LF

Dans un premier temps, nous allons implémenter une version simple de ce protocol, sans ajouter à la trame l'adresse d'un destinataire, ni la valeur numérique permettant de vérifier l'intégrité des données de la trame. La gestion "Error Checking" du protocole (vérification d'erreur) ne sera donc pas implémentée.

Le but est simplement de pouvoir capturer une trame au format ASCII de manière autonome, en créant une machine à états.

Start Data End
':' N Chars CR LF

Pour la réception de données à travers le port COM principale de la carte Arduino, nous utiliserons la fonction serialEvent() et nous prendrons soin de ne pas écraser un message par un nouveau avant d'avoir pu le lire.

Pour cela vous pouvez vous inspirez du diagramme d'états ci-dessous.


Quelques protocoles de communication que l'on retrouve sur le port série

Les communications séries sont encore aujourd'hui un moyen simple et souple pour mettre de l’intéraction entre la carte Arduino et votre ordinateur, voir d'autres périphériques.

Votre sketch Arduino pourra utiliser le port série pour accéder indirectement (souvent en utilisant un programme sur votre PC développé par exemple en langage Processing ou en Python) aux ressources de votre ordinateur et ainsi créer de l'interactivité.

Dans l’autre sens, votre ordinateur saura évidement intéragir avec certains capteurs ou périphériques connectés à votre Arduino.

La mise en place de protocoles de communication permettent une transmission de données structurées, cohérentes et vérifiables, car des erreurs de transmission peuvent survenir lors de l'émission, du transport ou de la réception.

Parmi les protocoles de communication citons en quelques uns parmis tant d'autres :


Terminal ou moniteur série

L'utilisation d'un logiciel coté PC, vous permettra d'écouter et de parler à votre carte Arduino.

Vous pouvez utiliser le Serial Monitor de l’IDE Arduino, sinon voici quelques outils disponibles çà et là sur le Web :

Nous vous proposons également de réaliser votre propre terminal série en langage Python, pour cela allez sur la branche serialevent-string-vers-terminal-python.


Algorithme d'émission/réception d'un message Modbus ASCII

modbus-ascii-fsm-message

Source : http://www.ozeki.hu/p_5855-ozeki-modbus-ascii.html


Test de reception d'une trame

Exemple de messages que doit recevoir le microcontrôleur pour changer l'état de notre LED :

":LED ON\r\n"
":LED OFF\r\n"
":LED TOGGLE\r\n"

Mais si vous essayez d'écrire une commande en minuscule, ça ne fonctionne pas :

":led toggle\r\n"

La raison est que ce qui est transmis du PC au microcontrôleur ne sont que des nombres :

Numéro TXD 1 2 3 4 5 6 7 8 9 10 11 12 13
Type char ':' 'L' 'E' 'D' ' ' 'T' 'O' 'G' 'G' 'L' 'E' '\r' '\n'
Valeur Hexa 0x3A 0x4C 0x45 0x44 0x20 0x54 0x4F 0x47 0x47 0x4C 0x45 0x0D 0x0A
Numéro TXD 1 2 3 4 5 6 7 8 9 10 11 12 13
Type char ':' 'l' 'e' 'd' ' ' 't' 'o' 'g' 'g' 'l' 'e' '\r' '\n'
Valeur Hexa 0x3A 0x6C 0x65 0x64 0x20 0x74 0x6F 0x67 0x67 0x6C 0x65 0x0D 0x0A

On peut remarquer que les caractères en minuscule ont une valeur de codage supérieure de + 0x20 par rapport aux même lettres en majuscule. Ce codage est défini par le code ASCII, voir aussi la table ASCII


Codage réalisé

A partir de l'exemple Serial Event d'Arduino, nous avons commencé à modifier la manière de recevoir les données pour créer une machine à états.

Git Graph, l'extension pour Visual Studio Code

Visualiser l'extention Git Graph

Les branches de se projet on été renommées :

Arnauld                  --> serialevent-mae-rx-vers-ab
Arnauld-Trame-Avec-CRC16 --> serialevent-mae-rx-crc16-vers-ab
arnaud                   --> serialevent-mae-rx-class-vers-cf
Terminal.py              --> serialevent-string-vers-terminal-python

Code de la branche main

Utilisation direct de l'exemple Serial Event d'Arduino avec notament l'utilisation de la class String.


Code de la branche serialevent-mae-rx-class-vers-cf de CrazyFraug

Découpage en différentes fonctions et utilisation d'une class, une par action à réaliser.

// we implement a state machine, we declare all possible sate values
enum class StateM { idle, received, rx_waiting_end_lf, emission, emission_start, emission_end };
StateM stateOfMachine = StateM::idle;

// the programme will be split in functions, each correspond to a state value
void stateIdle();
void stateReceived();
void stateRXWaitingEndLF(String& amsgModbus);
void stateEmission();
void stateEmissionStart();
void stateEmissionEnd();

Le traitement du message est séparé de la lecture buffer.

La machine à états principale pour la reception est dans la fonction :

void readSerialWithStateMachine(String& amsgModbus)


Code de la branche serialevent-mae-rx-vers-ab de ArnauldDev

Mise en oeuvre de l'implementation d'une machine à états en utilisant plutot un tableau de char comme buffer de réception.

/* Variable globales                                                         */
char g_message_recu[MAX_FRAME_LENGTH]; // buffer qui stocke les caractères ASCII reçu
uint8_t g_compteur_msg_perdu = 0;      // permet de savoir si l'on a loupé la lecture d'un ou plusieurs messages
bool g_nouveau_message_a_lire = false; // si vrai, indique qu'un nouveau message est disponible

Code de la branche serialevent-mae-rx-crc16-vers-ab de ArnauldDev

Ajouter le calcul et l'integration du CRC16 pour la reception d'un message.

About

Démarrage d'un projet collaboratif

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages