LA COMMUNICATION SERIE

Sources : https://learn.sparkfun.com/tutorials/serial-communication
https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
https://jeffskinnerbox.wordpress.com/2012/12/05/raspberry-pi-serial-communication/
http://www.jujens.eu/posts/2014/May/05/Communication-serie/

Il s'agit d'un concept de mise en oeuvre des échanges de données numérique entre système informatiques.
L idée est de transmettre en série ce qu'envoie un les n lignes d'un port parallèle.
Un port parallèle peut envoyer 8bits en un échange quand sa connectique est composée de 8 canaux de data.
Pour envoyer la même quantité de donnée, comme le port série ne dispose que d'un seul canal, il devra envoyer les 8 bits les uns à la suite des autres …

Pour cela, les communications séries incluent souvent la notion de d'horloge.

1. RX/TX : Les premières liaisons séries.

Le TX d'un device correspond à la broche qui émet. Le RX correspond à celle qui recoit.
C'est pour cela que les connections sont croisées !!!



Sur le raspberrypi et sur l'arduino, on voit des broches RX et TX.
Attention, à la base, les liaisons séries RX/TX étaient utilisées pour ne mettre en oeuvre une communication qu'entre 2 machines.
C'est encore le cas avec ces broches sur le raspberry pi.
En effet, cela ne permet de faire communiquer un maitre avec qu'avec 1 et 1 seul slave avec les mêmes broches RX/TX de connections du maitres. Sinon, il y aurait concurrent de lecture des données des slaves et d'écriture sur 1 slave ou un autre (Remarque : Le standard SPI règle ce problème)

D'autre part, comme aucun canal horloge n'est utilisé dans ce système, on doit définir la fréquence d'horloge pour le slave et pour le maitre. C'est sans doute pour cela qu'il faut la définir pour exécuter les programme ino de l'Arduino et dans les programmes d'un PC communiquant en série avec l'arduino. =⇒ Si on veut connecter un module communiquant en série avec l'Arduino avec ce mode RX/TX, il faudra auparavant connaitre sa fréquence d'horloge, qui correspond aussi à son taux de transfert (Baud = Symboles (de 8 bits)/secondes)

2. Les premiers standards de communication utilisés sont le TTL et RS-232.

Dans ces standards, chaque mot est codé sur un nombre de bits constant (par exemple, 8bits). Le même canal sert à transmettre les débuts de mot, les fins de mot, et les mots eux mêmes. A chaque mot, on associe un bit de début et un bit de fin. Dans les images qui suivent, les mots sont des mots de 8 bits. Le mot, avec ses bits de début et de fin, font normalement 10 bits. (Certains standards code la fin d'un mot sur 2 bits …)

TTL : When microcontrollers and other low-level ICs communicate serially they usually do so at a TTL (transistor-transistor logic) level.
TTL serial signals exist between a microcontroller’s voltage supply range - usually 0V to 3.3V or 5V.
A signal at the VCC level (3.3V, 5V, etc.) indicates either an idle line, a bit of value 1, or a stop bit.
A 0V (GND) signal represents either a start bit or a data bit of value 0.

——————————————————————————————————————————————————


RS-232 :
RS-232, which can be found on some of the more ancient computers and peripherals, is like TTL serial flipped on its head.
RS-232 signals usually range between -13V and 13V, though the spec allows for anything from +/- 3V to +/- 25V.
On these signals a low voltage (-5V, -13V, etc.) indicates either the idle line, a stop bit, or a data bit of value 1.
A high RS-232 signal means either a start bit, or a 0-value data bit. That’s kind of the opposite of TTL serial.

——————————————————————————————————————————————————


Remarque1 : Between the two serial signal standards, TTL is much easier to implement into embedded circuits.
However the low voltage levels are more susceptible to losses across long transmission lines.
RS-232, or more complex standards like RS-485, are better suited to long range serial transmissions.

Remarque2 : When you’re connecting two serial devices together, it’s important to make sure their signal voltages match up.
You can’t directly interface a TTL serial device with an RS-232 bus. You’ll have to shift those signals!

3. SPI : Un protocole amélioré, synchrone (avec horloge) qui introduit la notion de maitre.

- 2 broches de communication, chaque dédié à un sens, nommées SDI/SDO ou MOSI (MasterOutSlaveIn) /MISO(MasterInSlaveOutput)
- 1 broche nommée SCLK par slave pour que le maitre donne l'horloge aux slaves
- 1 broche nommée SS ou NSEL par maitre et par slave pour que le maitre puisse sélectionner le slave avec lequel il communique





Les étapes de la communication sont les suivantes :
Etape1 : Le maitre sélectionne (active) un de ses esclaves, en settant sa broche SS à 0V (Les slaves se débrouille pour positionner par defaut leur SS à n volt DC).
Etape2 : La communication se fait dans les 2 sens entre le maitre et l'esclave
A chaque front montant ou descendant d'horloge, 1 bit est échangé du slave vers le maitre (canal MISO) et du maitre vers le slave (canal MOSI).
On parle donc ici de communication full-duplex (A serial interface where both devices may send and receive data is either full-duplex or half-duplex. Full-duplex means both devices can send and receive simultaneously. Half-duplex communication means serial devices must take turns sending and receiving. ) On parle aussi de registre à décalage, car chaque nouveau bit recu par un des module pousse les autres bits deja recu dans le registre global.
Etape3 : A la fin de la séquence, qui est souvent de 8bits, le maitre désactive le slave en laissant libre la broche SS, qui se repositionnera à N volts, suivant le slave.

En fait, il y a 4 paramétrage pour les échanges, qui sont les combinaisons du :
- CPOL : positionnement sur l'horloge (valeur de base quand l'horloge est inactive = 0 ou 1).
- CPHA : capture des valeurs des bits au front montant ou descendant
Le schéma suivant montre les 4 différentes possibilités :

——————————————————————————————————————————————————


Par exemple, dans tous ces schémas, par exemple, si l'horloge est configurée en CPOL=1, et si le slave est configuré en CPHASE=0, alors les échanges MOSI/MISO entre master et slave se feraient sur front descendant de l'horloge.

Remarques : Dans ce mode de communication, même si l'intention n'est qu'une lecture, ou une écriture, les bits seront envoyé dans les 2 sens.
En fait, dans le cas ou le maitre n'a rien à écrire, il enverra une séquence dite 'dummy' (que des 0? ou que des 1?) qui devra être considérée comme dummy par le slave. Idem dans l'autre sens, si le slave n'a rien à écrire, il enverra une séquence dite 'dummy'.



4. UART : un autre protocole asynchrone universel

4.1 : Coté protocole d'échange, + UART est asynchrone, parce que : ces dispositifs n'ont pas besoin d'un canal d'horloge pour échanger (il se servent de la durée des bits (=1/baudrate), qui est prédéfinie (en général, le slave en a qu'une)) + UART est dit universel parce que : la vitesse et la taille des données ne sont pas fixes et peuvent être configurés pour répondre aux besoins d'une exigence de communication donnée, même si cela signifie que les deux côtés de la conversation doivent déjà s'être entendus sur ces paramètres.

Du coup, de ce que je comprend, ca ressemble énormément mais en fait, ce n'est pas la même chose que le RS-232 : L'UART n'est pas un standard de communication, comme peuvent l'être RS-232, RS-422, RS-485. C'est plutôt un équipement qui permet d'envoyer en série des séquence de bits, mais leur signification, selon leur ordre et leur valeurs de ces bits ne sont pas spécifiées par l'UART. Ce qui pourrait les définir, c'est par exemple la norme RS-232, RS-422 ou autre norme propriétaire. D'autre part, il existe une différence dans les voltages entre les signaux de l'UART et ceux d'un équipement RS-232 : - pour le RS-232 c'est du [-nVolt +nVolt] n < 25, - alors que UART c'est > 0, ⇐ 5V Il faut donc pour faire communiquer [ PC –> Equipement_UART (portParallele –> portSerie) –> ] –> Convertisseur Voltages –> RS-232

L'autre différence entre UART et RS-232, c'est que l'UART dipose d'une interface port série ←→ port parallèle (voir section 4.2).

4.2 : Coté récupération des données L'UART se distingue en mettant en place un registre disposant du nombre de bits des mots échangés (donc en général 8 bits). A chaque bit de donné d'un mot en cours de réception, le registre est décalé d'un bit et le bit arrivant est placé en tête de registre. Une fois le mot entièrement échangé, le registre est prêt à être lu par le maitre. Ca permet donc au maitre (un PC) de lire des octets, plutôt que d'avoir à gérer des bits 1 à 1.

Pour l'écriture du maitre vers les slaves, il n'y a pas besoin d'un registre, les bits sont envoyés directement, avec biensur le bit de début, le bit de fin (précédent éventuellement d'un bit de parité.)



UARTs do exist as stand-alone ICs, but they’re more commonly found inside microcontrollers.
You’ll have to check your microcontroller’s datasheet to see if it has any UARTs.
Some have none, some have one, some have many.
For example, the Arduino Uno - based on the “old faithful” ATmega328 - has just a single UART, while the Arduino Mega - built on an ATmega2560 - has a whopping four UARTs.

Les dispositifs UART les plus avancés bufferisent les données qu'ils recoivent ; les octets sont enregistrés de manière asynchrone dans une FIFO, jusqu'à ce que le microprocesseur demande à les récupérer. La taille de ces buffers peut aller de quelques octets à des milliers d'octets.



5. Interfaces de communications GPIO sur le raspberry :



Heureusement, ces standards de communications en série ont été développées et mis à disposition par les développeurs, sous forme de librairies.
Par exemple, celle de wiringPi (en C), qui permet de communiquer avec les ports séries, ou avec les périphériques usb série https://projects.drogon.net/raspberry-pi/wiringpi/serial-library/
Il existe aussi des librairies python pour le raspberry (voir mon article gpio), comme par exemple http://www.jujens.eu/posts/2014/May/05/Communication-serie/ :

Mise en place d'une connections série entre le raspberry pi2 et un périphérique communiquant en série
1. En série via les GPIOs
Dans ce cas, il faut utiliser le device /dev/ttyAMA0 dans le code python donné ci-dessous (je pense que ce device est directement lié aux PIN RX et TX du RBPI2)
Remarque : En cas d'échec intempestifs de lecture ou d'écrire, il convient de désactiver l'option de login aux système à partir du port série (ces 2 GPIO).
Pour ce faire, on tape raspi-config –> Advanced Options –> A8 Serial Enable/Disable shell and kernel … –> Répondre “no” à “Shell to be accessible over serial”
Ok, j'ai testé avec le programme ci-dessous ça fonctionne.
Il ne faut pas oublier d'alimenter l'arduino ; je l'ai alimenté en externe via un chargeur USB, mais on peut l'alimenter en 5V directement à partir du RBPI2 via son GPIO 5V


2. via USB
J'ai aussi testé et ça fonctionne aussi ; il ne suffit que de brancher un cable usb entre le rbpi2 et l'arduino. On peut bien évidemment brancher l'arduino sur un hub USB connecté au RBPI2. La prise USB servira alors d'alimentation au RBPI2 et de bus série.

3. via I2C (encore un peu plus chiant)

Exemple E1 de programmes communiquants : E1.Etape1. : Sur l'arduino, téléverser le script suivant qui renvoie ce qu'il a recu en rajoutant devant la chaine “chaine recue et renvoyee:”

testArduino.ino
    int byte_read = 0; ///< The current byte
    bool dataHasBeenReaden = false;
    char s[512] = "";
    int cpt=0;
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    }
 
    void loop()  // put your main code here, to run repeatedly:
    {      
      dataHasBeenReaden = false;
      cpt = 0;
      while ( Serial.available() ) 
      {
          dataHasBeenReaden = true;
          byte_read = Serial.read();
          s[cpt] = byte_read;
          cpt++;
          //Serial.print("byte%i:");
      }
      if (dataHasBeenReaden)
      {
        Serial.print("chaine recue et renvoyee:");   
        Serial.println(s);   
      }
      delay(1000);

E1.Etape2. : Connecter l'arduino uno en USB sur le rbpi2 Faire un #lsusb –> montre que l'Arduino uno a bien été détecté Faire un #dmesg –> on retrouve le device système : /dev/ttyACM0

E1.Etape3. : Sur le raspberry, écrire ce script, en remplaçant /dev/ttyACM0 par le nom de votre port

testSerieFromRBPI.py
	from serial import Serial
    serial_port = Serial(port='/dev/ttyACM0', baudrate=9600) # ou serial_port = Serial("/dev/ttyAMA0", baudrate=9600, timeout=0.5)
    lu = serial_port.write("la donnee est bonne")
    lu = serial_port.readline()
    lu # renvoie 'chaine recue et renvoyee:la donnee est bonne\r\n'
    Serial.close(serial_port)