Outils pour utilisateurs

Outils du site


wiki:tutoriels:arduino:evoyer_float_via_port_serie

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
wiki:tutoriels:arduino:evoyer_float_via_port_serie [2020/06/29 15:23]
damien.muti [Capteur de distance Ultrason Grove]
wiki:tutoriels:arduino:evoyer_float_via_port_serie [2021/06/16 08:50] (Version actuelle)
damien.muti [Solution 2 : envoi des différents octets]
Ligne 1: Ligne 1:
-====== ARDUINO : COMMENT ENVOYER DES DONNÉES DE TYPE FLOAT OU DOUBLE VIA LE PORT SÉRIE  ======+====== ARDUINO : COMMENT ENVOYER DES DONNÉES DE TYPE FLOATDOUBLE OU INT SUPÉRIEUR 255 VIA LE PORT SÉRIE  ======
  
   * Porteur(s) du projet :  Damien MUTI DESGROUAS    * Porteur(s) du projet :  Damien MUTI DESGROUAS 
-  * Date : 26/03/2020+  * Date : 03/11/2020
   * Licence : libre !   * Licence : libre !
   * Contexte : Apprentissage   * Contexte : Apprentissage
- 
------------------------------A terminer : voir tutoriel "capteurs arduino - Bluetooth " ------------------- 
  
 ===== introduction ===== ===== introduction =====
-  +==== Les modes de communications entre Arduino et Processing ==== 
-Dans ce tutoriel,  +La communication via le port série de la carte **Arduino** utilise principalement deux fonctions : 
-===== Capteurs =====+  * [[https://www.arduino.cc/reference/en/language/functions/communication/serial/write/|Serial.write()]] :  Écrit des données binaires sur le port série. Ces données sont envoyées sous forme d'octet ou de série d'octets. 
 +  * [[https://www.arduino.cc/reference/en/language/functions/communication/serial/print/|Serial.print()]] :  Imprime les données sur le port série sous forme de texte ASCII lisible par l'homme. Cette commande peut prendre plusieurs formes. Les nombres sont imprimés en utilisant un caractère ASCII pour chaque chiffre. Les flottants sont imprimés de la même manière sous forme de chiffres ASCII, avec par défaut deux décimales. Les octets sont envoyés sous la forme d'un seul caractère. Les caractères et les chaînes sont envoyés tels quels. 
 +  * [[https://www.arduino.cc/reference/en/language/functions/communication/serial/println/|Serial.println()]] :  Imprime les données sur le port série sous forme de texte ASCII lisible par l'homme suivi d'un caractère de retour chariot (ASCII 13 ou '\ r') et d'un caractère de nouvelle ligne (ASCII 10 ou '\ n'). Cette commande prend les mêmes formes que [[https://www.arduino.cc/reference/en/language/functions/communication/serial/print/|Serial.print()]]. 
 + 
 + 
 +Lorsque la carte Arduino communique avec le logiciel **Processing**, ce dernier utilise la librairie [[https://www.processing.org/reference/libraries/serial/index.html|Serial]]. Pour lire une donnée sur le port série il est possible d'utiliser plusieurs méthodes : 
 +  * [[https://www.processing.org/reference/libraries/serial/Serial_read_.html|read()]] : Cette méthode renvoie un nombre compris entre 0 et 255 codé uniquement sur un octet. Elle renvoie -1 lorsque le port est vide et qu'il n'y a aucune donnée reçue. Pour contourner ce dernier problèmeil convient d'abord de tester si une donnée est disponible sur le port série grâce à la méthode //available()//
 +  * [[https://www.processing.org/reference/libraries/serial/Serial_readString_.html|readString()]] : Cette méthode renvoie toutes les données contenue dans le buffer du port série sous forme de d'une chaîne de caractère (String) ou renvoie //null// aucune donnée n'est disponible sur le port série. Cette méthode suppose que les caractères entrants sont codés en ASCII. 
 + 
 + 
 +==== Problème ==== 
 + 
 +Pour envoyer des nombres, Arduino est contraint de les coder uniquement sur un octet, via la méthode [[https://www.arduino.cc/reference/en/language/functions/communication/serial/write/|Serial.write()]]. De même, le logiciel Processing ne peut recevoir que des nombres codés sur un octet via la méthode [[https://www.processing.org/reference/libraries/serial/Serial_read_.html|read()]] issue de la librairie [[https://www.processing.org/reference/libraries/serial/index.html|Serial]]. 
 + 
 +Ceci contraint fortement le dialogue entre la carte Arduino et le logiciel Processing car, dès lors, il n'est possible  d'envoyer et de recevoir que des nombres entiers compris entre 0 et 255. 
 + 
 +==== Solution 1 : envoi d'une String ==== 
 +Pour contourner ce problème, une des solution est de convertir le nombre (//float, int, long, double//, etc.) en une chaîne de caractère (//String//) et d'envoyer cette chaîne sur le port série via la méthode [[https://www.arduino.cc/reference/en/language/functions/communication/serial/print/|Serial.print()]], du coté de la carte Arduino. 
 + 
 +Du coté de la réception sur l'application Processing, la chaîne de caractère envoyée par la carte Arduino sur le port série est d'abord lue par la méthode [[https://www.processing.org/reference/libraries/serial/Serial_readString_.html|readString()]] de la librairie [[https://www.processing.org/reference/libraries/serial/index.html|Serial]]. Ensuite, la chaîne est convertie en un entier grâce à la méthode [[https://www.processing.org/reference/intconvert_.html|int()]], ou en un nombre flottant grâce à la méthode [[https://www.processing.org/reference/floatconvert_.html|float()]]. 
 + 
 +Référence : 
 +  * [[https://forum.processing.org/one/topic/converting-string-to-int.html|Forum Processing : Converting String to int]] 
 + 
 +==== Solution 2 : envoi des différents octets ==== 
 +Une autre solution est d'envoyer les différents octets composant le nombre (//float, int, long, double//, etc.) sur le port série via la méthode [[https://www.arduino.cc/reference/en/language/functions/communication/serial/write/|Serial.write()]], du coté de la carte Arduino. Par exemple, un //int// sous Arduino est codé sur deux octets. Il suffira donc d'envoyer les deux octets départements, l'un à la suite de l'autre. 
 + 
 +Du coté de la réception sur l'application Processing, on réceptionne les différents octets correspondant au nombre envoyé par la carte. On concatène les octets reçus dans la variable adéquate.   
 + 
 +===== Application : Envoie de la distance lue par un capteur à ultrason ===== 
 +==== Montage ==== 
 +On utilise un [[wiki:tutoriels:arduino-capteurs:arduino-capteurs#capteur_de_distance_ultrason_grove|capteur à ultrason Grove]] pour mesurer une distance. On envoie ensuite la distance mesurée à l'application Processing. 
 +Il convient de brancher le capteur Grove sur l'entrée digitale D7. Le montage est le [[wiki:tutoriels:arduino-capteurs:arduino-capteurs#capteur_de_distance_ultrason_grove|suivant]] : 
 +{{ :wiki:tutoriels:arduino-capteurs:capteur_dist_ultrason_arduino_connection_grove.jpg?400 |}} 
 + 
 +==== Solution 1 : envoi d'une String ==== 
 +=== code Arduino === 
 +Le code Arduino est le suivant : 
 +<code> 
 +#include "Ultrasonic.h" 
 + 
 +Ultrasonic ultrasonic(7); 
 +void setup() { 
 +  Serial.begin(9600); 
 +
 +void loop() { 
 +  long distance; 
 + 
 +  distance = ultrasonic.MeasureInCentimeters(); // two measurements should keep an interval 
 +  Serial.print(distance);//0~400cm 
 +  //Serial.println(" cm"); 
 +  delay(250); 
 +
 +</code> 
 + 
 +Le code est disponible sur le lien suivant : {{ :wiki:tutoriels:arduino:ultrasonic_envoie_donn_es_port_serie.ino.zip |}}  
 + 
 +=== code Processing === 
 +Le code Processing est le suivant : 
 + 
 +<code> 
 +/* 
 +références : https://forum.processing.org/one/topic/converting-string-to-int.html 
 + */ 
 + 
 +import processing.serial.*; 
 + 
 +Serial myPort;  // Create object from Serial class 
 +String  inBuffer;      // Data received from the serial port 
 +int inEntier; 
 + 
 +void setup() { 
 +  size(200, 200); 
 +  // I know that the first port in the serial list on my mac 
 +  // is always my  FTDI adaptor, so I open Serial.list()[0]. 
 +  // On Windows machines, this generally opens COM1. 
 +  // Open whatever port is the one you're using. 
 + 
 +  // Print a list of the serial ports, for debugging purposes: 
 +  printArray(Serial.list()); 
 + 
 +  String portName = Serial.list()[32]; 
 +  myPort = new Serial(this, portName, 9600); 
 +
 + 
 +void draw() { 
 +  // lecture des données sur le port série 
 +  if ( myPort.available() > 0) {  // si une donnée est disponible sur le port série 
 +    inBuffer = myPort.readString(); // lire la donnée et la stoquer dans inBuffer (chaine de caractères - String)  
 +  } 
 +  //conversion des données String -> int 
 +  if (inBuffer != null) { // si la chaine de caractère n'est pas nulle 
 +    println("inBuffer="+inBuffer +"(String)"); //afficher la chaine de caractère inBuffer 
 +    inEntier=int(inBuffer); // convertir la chaine de caractère en un entier 
 +    println("inEntier="+inEntier+"(int)"); // afficher l'entier correcpondant 
 +  } 
 +   
 +  // test des données 
 +  color c ; 
 +  if (inEntier<25){ 
 +    c = color(255,0,0); 
 +  } 
 +  else{ 
 +    c = color(0,0,255); 
 +  } 
 +  fill(c); 
 +  rect(0,0,width,height); 
 +
 +</code> 
 + 
 +Le code est disponible sur le lien suivant : {{ :wiki:tutoriels:arduino:lecture_donnees_port_serie.pde.zip |}} 
 + 
 +==== Solution 2 : envoi des différents octets ==== 
 + 
 +Le projet global consiste à lancer un événement (vidéo, son, animation) lorsque la distance détectée est inférieure à un seuil, ou sur une certaine plage de distance. Ce programme est inspiré de celui effectué sur pour les [[wiki:tutoriels:processing:processing_9:processing_9|objets interactifs]].  
 + 
 +=== code Arduino === 
 +Le code Arduino est le suivant : {{ :wiki:tutoriels:arduino:ultrasonic_envoie_donnees_port_serie_1.zip |}} 
 + 
 +<code> 
 +#include "Ultrasonic.h" 
 + 
 +Ultrasonic ultrasonic(7); 
 +int distance =354; 
 +int inByte = 0;         // incoming serial byte 
 +// debug 
 +boolean debug = false; 
 + 
 +void setup() { 
 +  Serial.begin(9600); 
 +  while (!Serial) { 
 +    ; // wait for serial port to connect. Needed for native USB port only 
 +  } 
 +  establishContact();  // send a byte to establish contact until receiver responds 
 + 
 +  // création du tableau d'octets  
 +
 +void loop() { 
 +  if (Serial.available() > 0) { 
 +    // get incoming byte: vider le port série 
 +    inByte = Serial.read(); 
 +    // lire la valeur de la distance 
 +    distance = ultrasonic.MeasureInCentimeters(); 
 +    // envoyer la distance sur la port série sous la forme d'une chaine de caractères 
 +    if (debug) { 
 +      Serial.print("distance="); 
 +      Serial.print(distance);//0~400cm 
 +      Serial.println("cm"); 
 +    } 
 +    else { // envoie des données brutes : un int est sur 2 octets 
 +      Serial.write(0xFF & distance >> 8);// octet de poids fort 
 +      Serial.write(0xFF & distance);// octet de poids faible 
 +       
 +       
 +    } 
 +    //delay(10); 
 +  } 
 +
 + 
 +void establishContact() { 
 +  while (Serial.available() <= 0) { 
 +    Serial.print('A');   // send a capital A 
 +    delay(300); 
 +  } 
 +
 +</code> 
 +=== code Processing === 
 +Le programme global correspondant à un [[wiki:tutoriels:processing:processing_9:processing_9|objet interactif]] est le suivant : {{ :wiki:tutoriels:arduino:detection_porte_2.zip |}} 
 + 
 + 
 +Nous ne présentons ici que la partie de réception des données par la méthode //serialEvent()//. Le code Processing est le suivant :  
 + 
 +<code> 
 +void serialEvent(Serial myPort) { 
 +  // read a byte from the serial port: 
 +  int inByte = myPort.read(); 
 +  // if this is the first byte received, and it's an A, 
 +  // clear the serial buffer and note that you've 
 +  // had first contact from the microcontroller.  
 +  // Otherwise, add the incoming byte to the array: 
 +  if (firstContact == false) { 
 +    if (inByte == 'A') {  
 +      myPort.clear();          // clear the serial port buffer 
 +      firstContact = true;     // you've had first contact from the microcontroller 
 +      myPort.write('A');       // ask for more 
 +    }  
 +  }  
 +  else { 
 +    // Add the latest byte from the serial port to array: 
 +    serialInArray[serialCount] = inByte; 
 +    serialCount++; 
 + 
 +    // If we have nbBytes=2 bytes: 
 +    if (serialCount > nbBytes-1 ) { 
 +      // concaténer les deux octets reçus 
 +      donneePortSerie = int(serialInArray[0] << 8) + int(serialInArray[1]) ; 
 +       
 +      // print the values (for debugging purposes only): 
 +      //println(serialInArray[0] + "\t" + serialInArray[1]+"\t" + donneePortSerie); 
 +      println("distance=" + donneePortSerie + "cm"); 
 + 
 +      // Send a capital A to request new sensor readings: 
 +      myPort.write('A'); 
 +      // Reset serialCount: 
 +      serialCount = 0; 
 +    } 
 +  } 
 +
 +</code>
  
wiki/tutoriels/arduino/evoyer_float_via_port_serie.1593437032.txt.gz · Dernière modification: 2020/06/29 15:23 de damien.muti