La communication via le port série de la carte Arduino utilise principalement deux fonctions :
Lorsque la carte Arduino communique avec le logiciel Processing, ce dernier utilise la librairie Serial. Pour lire une donnée sur le port série il est possible d'utiliser plusieurs méthodes :
Pour envoyer des nombres, Arduino est contraint de les coder uniquement sur un octet, via la méthode Serial.write(). De même, le logiciel Processing ne peut recevoir que des nombres codés sur un octet via la méthode read() issue de la librairie 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.
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 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 readString() de la librairie Serial. Ensuite, la chaîne est convertie en un entier grâce à la méthode int(), ou en un nombre flottant grâce à la méthode float().
Référence :
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 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.
On utilise un 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 suivant :
Le code Arduino est le suivant :
#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); }
Le code est disponible sur le lien suivant : ultrasonic_envoie_donn_es_port_serie.ino.zip
Le code Processing est le suivant :
/* 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); }
Le code est disponible sur le lien suivant : lecture_donnees_port_serie.pde.zip
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 objets interactifs.
Le code Arduino est le suivant : ultrasonic_envoie_donnees_port_serie_1.zip
#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); } }
Le programme global correspondant à un objet interactif est le suivant : 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 :
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; } } }