Site icon AranaCorp

Communication série entre Raspberry Pi et Arduino

Dans certains projets, il peut être intéressant d’établir une communication série entre Raspberry Pi et Arduino. Il est ainsi possible de coupler la puissance de calcul et les interface sans fil du Raspberry Pi avec les entrées-sorties et la collection de modules Arduino. Le premier exemple qui vient en tête est l’utilisation de ce système pour de la domotique dans lequel le Raspberry Pi va héberger l’interface de contrôle et l’intelligence et les Arduino vont servir d’automate programmable agissant sur les composants en bout de chaîne (lumière, radiateur, ventilateur, capteurs, etc.).

Nous allons voir dans ce tutoriel comment mettre en place une communication série entre Raspberry Pi et Arduino via le port USB. Dans cet article, nous utilisons la carte Arduino UNO mais il peut être adapté à d’autre type de carte avec une connexion série (Nano, Mega, Feather, EPS32, ESP8266 etc.)

Prérequis: Communication Série avec Arduino, Accès à distance du Raspberry Pi avec VNC

Matériel

Schéma de câblage

Pour établir la communication série entre Raspberry Pi et Arduino, il suffit des les relier grâce à un câble USB adapté. Dans notre cas, nous utilisons un Raspberry Pi 3B+ et un Arduino UNO. Il nous faut donc un cable USBA Mâle vers USB B Mâle.

Il est aussi possible de créer une communication série en utilisant les broches Rx/Tx des deux composants. Dans ce tutoriel, nous allons nous concentrer sur la connexion USB

Configuration du Raspberry Pi

Nous rappelons que pour pouvoir utiliser votre Raspberry Pi sans écran ni clavier, il faut que la connexion à distance VNC soit configurée.

Pour utiliser l’interface Série du Raspberry Pi, celle-ci doit être activée dans le menu de configuration. Pour cela entrez la commande suivante dans un terminal:

sudo raspi-config

Dans le menu, sélectionnez « 5 – Interfacing Options » puis « P6 Serial » et validez.

Un fois le branchement fait, vous pouvez vérifier les appareils branchés sur le port série en tapant dans le terminal la commande:

lsusb

Le Raspberry Pi retourne la liste des appareils branchés sur les ports USB.

pi@raspberrypi:~ $ lsusb
Bus 001 Device 002: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Pour trouver le nom du port sur lequel est branché l’Arduino, nous utilisons la commande:

dmesg | grep "tty"

Cette commande retourne les message système relatifs aux port séries. Vous deviez trouver le nom du port dans les derniers message. Dans notre cas le nom du port est ttyACM0.

pi@raspberrypi:~ $ dmesg | grep "tty"
[    0.000000] Kernel command line: coherent_pool=1M 8250.nr_uarts=1 bcm2708_fb.fbwidth=1824 bcm2708_fb.fbheight=984 bcm2708_fb.fbswap=1 smsc95xx.macaddr=B8:27:EB:23:CF:07 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000  console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
[    0.000636] console [tty1] enabled
[    0.951553] 20201000.serial: ttyAMA0 at MMIO 0x20201000 (irq = 81, base_baud = 0) is a PL011 rev2
[    0.954393] console [ttyS0] disabled
[    0.954466] 20215040.serial: ttyS0 at MMIO 0x0 (irq = 53, base_baud = 31250000) is a 16550
[    0.954570] console [ttyS0] enabled
[    5.378641] systemd[1]: Created slice system-serial\x2dgetty.slice.
[ 1455.402071] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
[ 1581.980257] cdc_acm 1-1:1.0: ttyACM0: USB ACM device

Installation de l’IDE Arduino sur Raspberry Pi

Pour installer l’IDE Arduino sur Raspberry Pi, le mieux est de passer par le terminal. Il vous suffit de rentrer les lignes de code suivantes:

mkdir ~/Applications
cd ~/Applications
wget https://downloads.arduino.cc/arduino-1.8.9-linuxarm.tar.xz
tar xvJf arduino-1.8.9-linuxarm.tar.xz
cd arduino-1.8.9/
 ./install.sh
rm ../arduino-1.8.9-linuxarm.tar.xz

Ceci vous permettra, par la suite, de programmer l’Arduino directement à partir du Raspberry Pi.

Code

Code Arduino

La librairie utilisée pour la communication série côté Arduino est la même que pour communiquer avec le moniteur série, la librairie Serial.h que nous connaissons bien. Vérifiez bien que la vitesse de communication est la même pour les deux appareils (baudrate=9600) sinon la communication ne fonctionnera pas.

String nom = "Arduino";
String msg;

void setup() {
  Serial.begin(9600);
}

void loop() {
  readSerialPort();

  if (msg != "") {
    sendData();
  }
  delay(500);
}

void readSerialPort() {
  msg = "";
  if (Serial.available()) {
    delay(10);
    while (Serial.available() > 0) {
      msg += (char)Serial.read();
    }
    Serial.flush();
  }
}

void sendData() {
  //write data
  Serial.print(nom);
  Serial.print(" received : ");
  Serial.print(msg);
}


Code Python

Dans ce tutoriel, nous allons utiliser le langage Python côté Raspberry Pi. La librairie utilisée pour la gestion de la communication série est la librairie serial.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# lsusb to check device name
#dmesg | grep "tty" to find port name

import serial,time


if __name__ == '__main__':
	
	print('Running. Press CTRL-C to exit.')
	with serial.Serial("/dev/ttyACM0", 9600, timeout=1) as arduino:
		time.sleep(0.1) #wait for serial to open
		if arduino.isOpen():
			print("{} connected!".format(arduino.port))
			try:
				while True:
					cmd=input("Enter command : ")
					arduino.write(cmd.encode())
					#time.sleep(0.1) #wait for arduino to answer
					while arduino.inWaiting()==0: pass
					if  arduino.inWaiting()>0: 
						answer=arduino.readline()
						print(answer)
						arduino.flushInput() #remove data after reading
			except KeyboardInterrupt:
				print("KeyboardInterrupt has been caught.")

Résultat

Le Raspberry Pi envoie la commande « Hello Arduino » à l’Arduino, et l’Arduino répond avec son nom et la commande reçu.

Exemple pratique

Une fois que la communication est établie entre Raspberry Pi et Arduino, ce qui est intéressant, c’est de piloter les entrées-sorties de l’Arduino et de récupérer les valeurs des capteurs. Dans cet exemple, nous allons définir différentes commandes:

Code Arduino

L’Arduino, renvoie des données lorsqu’elle reçoit la commande « data » et allume et éteint la LED branchée sur la broche 13 en fonction des commandes « led0 » et « led1 ».

const int ledPin=13;
String nom = "Arduino";
String msg;

void setup() {
  Serial.begin(9600);
}

void loop() {
  readSerialPort();

  if (msg == "data") {
    sendData();
  }else if(msg=="led0"){
    digitalWrite(ledPin,LOW);
    Serial.print(" Arduino set led to LOW");
  }else if(msg=="led1"){
    digitalWrite(ledPin,HIGH);
    Serial.print(" Arduino set led to HIGH");
  }
  delay(500);
}

void readSerialPort() {
  msg = "";
  if (Serial.available()) {
    delay(10);
    while (Serial.available() > 0) {
      msg += (char)Serial.read();
    }
    Serial.flush();
  }
}

void sendData() {
  //write data ledState x sensor1 x sensor2
  Serial.print(digitalRead(ledPin));
  Serial.print("x");
  Serial.print(analogRead(A0));
  Serial.print("x");
  Serial.print(analogRead(A1));
}


Code Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# lsusb to check device name
#dmesg | grep "tty" to find port name

import serial,time


if __name__ == '__main__':
	print('Running. Press CTRL-C to exit.')
	with serial.Serial("/dev/ttyACM0", 9600, timeout=1) as arduino:
		time.sleep(0.1) #wait for serial to open
		if arduino.isOpen():
			print("{} connected!".format(arduino.port))
			try:
				while True:
					cmd=input("Enter command (data,led0 or led1): ")
					arduino.write(cmd.encode())
					#time.sleep(0.1) #wait for arduino to answer
					
					while arduino.inWaiting()==0: pass
					if  arduino.inWaiting()>0: 
						answer=str(arduino.readline())
						print("---> {}".format(answer))
						if cmd=="data":
							dataList=answer.split("x")
							print("led state : {}".format(dataList[0]))
							print("Analog input A0 : {}".format(dataList[1]))
							print("Analog input A1: {}".format(dataList[2]))
							
							arduino.flushInput() #remove data after reading
							
			except KeyboardInterrupt:
				print("KeyboardInterrupt has been caught.")

Une fois les deux codes téléversés et lancés, on observe que lorsqu’on entre la commande « data » dans le terminal, Arduino renvoie bien des bytes contenant les valeurs de capteurs. Il est possible de séparer cette réponse en liste à l’aide de la fonction split() et du caractère « x » et, ainsi, récupérer les valeurs des capteurs et l’état de la led. Grâce à ce code, il nous est possible de piloter l’état de la LED de la broche 13.

En modifiant ce code, il vous sera possible de piloter et d’observer n’importe quelle entrée-sortie de l’Arduino sur le Raspberry Pi.

Application

Sources

Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

Quitter la version mobile