Raspberry Pi – Arduino – Lier les deux via le bus I2C


Achtung : Dieser Artikel wurde automatisch von Bing Translate übersetzt


Advertencia : Este artículo ha sido traducido automáticamente por Bing Translate

Certains disent qu’on ne lie pas des chiens avec des saucisses mais des fois pourquoi pas. Alors le Raspberry Pi et l’Arduino ne sont pas forcement aussi opposés, avec même des points communs mais chacun à des avantages qui peuvent être bons de combiner.

RaspArduinoI2CAvec le Raspberry Pi vous pouvez via les ports GPIO contrôler des composants externes et faire de la bidouille en électronique. Mais j’imagine que certains maitrisent déjà bien leur Arduino, qu’ils ont le matériel, etc. Et puis ça fait un tuto en plus 😀

Pour lier les deux, nous allons passer par le protocole I2C. Plusieurs raisons à ça : ne pas utiliser le port USB, le Raspberry Pi étant limité (si vous voulez le faire quand même il y a un article dans le MagPi #15 et j’en ferai un moi même plus tard). Et ne pas utiliser le port série. Ici c’est un peu plus personnel, car j’ai une carte Slice Of Pi sur un Raspberry pour la station météo et elle utilise le port série pour les sondes sans fil.

Le protocole I2C, créé par Philips avec une orientation domotique, permet à plusieurs composants de dialoguer entre eux de manière bidirectionnel mais en half-duplex uniquement. Comme d’habitude, plus d’infos chez Wikipedia.

Il y a un principe de maitre et esclave. Ici nous allons donc utiliser le Raspberry Pi en tant que maitre et l’Arduino en tant qu’esclave.

Avant tout pour connecter les deux appareils il faut savoir quelles broches utiliser !
Pour le raspberry c’est sur les GPIO 2 et 3 (pour les cartes à partir du modèle B révision 2, ceux avec les trous de fixation dans la carte)

raspberry-i2c

Pour l’Arduino, ça se passe sur les broches A4 et A5 pour les cartes de type Arduino Uno. Pour les autres cartes, vous trouverez plus d’informations sur le site officiel d’Arduino.

arduino-i2c-2Il faudra ajouter une connexion à la masse entre les deux. Donc vous aurez besoin de trois fils.

Avant de connecter nos deux appareils, il faut s’assurer qu’ils vont pouvoir communiquer. Toutes les informations sont sur le site d’adafruit mais en gros, voici ce qu’il faut faire.

Définir l’Arduino comme esclave

C’est relativement simple en incluant le module Wire dans le programme. J’ai pris l’adresse 0x12 mais vous pouvez choisir de 0x03 à 0x77 (en hexa) :

#include <Wire.h>

#define SLAVE_ADDRESS 0x12
int dataReceived = 0;

void setup() {
    Serial.begin(9600);
    Wire.begin(SLAVE_ADDRESS);
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);
}

void loop() {
    delay(100);
}

void receiveData(int byteCount){
    while(Wire.available()) {
        dataReceived = Wire.read();
        Serial.print("Donnee recue : ");
        Serial.println(dataReceived);
    }
}

void sendData(){
    int envoi = dataReceived + 1;
    Wire.write(envoi);
}

Vous l’aurez compris, le programme initialise l’Arduino avec l’adresse 0x12, définit la méthode de réception des données, la méthode d’envoi des données et c’est parti pour l’envoyer vers la carte avec l’interface.

Activer la gestion I2C sur le Raspberry Pi

Par défaut, des distributions de type Raspbian désactivent la gestion I2C pour économiser la mémoire utilisée par le module. Pour réactiver, rien de plus simple et c’est dans le fichier /etc/modprobe.d/raspi-blacklist.conf. Il faut mettre en commentaire avec un # la ligne :

blacklist i2c-bcm2708

Reste à activer le module lors de chaque démarrage. C’est dans le fichier /etc/modules, en y ajoutant à la fin une nouvelle ligne :

i2c-dev

Ensuite vous installez la suite des outils de gestion I2C

apt-get install i2c-tools

Il va vous falloir redémarrer le Raspberry pour faire apparaitre deux fichiers :

1._ssh-2
Grâce à eux vous allez pouvoir communiquer sur le bus I2C !

Vous pouvez lister les périphériques avec la commande :

i2cdetect -y 1

Pour les modèles 256Mo (comme celui que j’utilise pour mes tests) :

i2cdetect -y 0

Voilà. Etape suivante : connecter l’Arduino et lui parler !

Communiquer avec l’Arduino

Vous pouvez maintenant relier l’Arduino au Raspberry et allumer tout ce petit monde !

Attention, sur le schema, le raccordement SDA et SCL est inversé ! Le rouge en A5 et le balnc va en A4 😉

ArduinoRaspberry

Une fois fait, vous vous connectez sur le Raspberry Pi et vous relancez la commande i2cdetect avec le bon paramètre :

1._ssh-2

Le paramètre défini dans le sketch envoyé à l’Arduino, 0x12, apparait dans les périphériques détectés. On progresse !

Il nous faut maintenant mettre en place le script sur le Raspberry Pi qui va envoyer/recevoir avec l’Arduino. Pour cela, le plus simple c’est d’installer le support d’I2C dans les scripts Python. C’est ce que va faire python-smbus

apt-get install python-smbus

Nous sommes donc maintenant équipé pour parler à notre Arduino. Pour ça un petit programme tout simple. Envoyer un chiffre entre 0 et 8 et nous retourner ce chiffre plus un :

import smbus
import time

# Remplacer 0 par 1 si nouveau Raspberry
bus = smbus.SMBus(0)
address = 0x12

print "Envoi de la valeur 3"
bus.write_byte(address, 3)
# Pause de 1 seconde pour laisser le temps au traitement de se faire
time.sleep(1)
reponse = bus.read_byte(address)
print "La reponse de l'arduino : ", reponse

Le résultat de l’exécution :

1._ssh-2

Laisser parler votre imagination pour maintenant diriger l’Arduino en lui envoyant des demandes un peu plus complexes en fonction de ce que vous aurez de branché dessus !

Source et inspiration : un article d’Oscar

Vous aimerez aussi...

  • ubik75

    Bonjour,

    Suite à la lecture de l’article, je me demande s’il ne faut ajouter entre le raspberry et l’arduino un convertisseur logique afin de protéger le 3,3V du Pi du 5V de l’arduino ?

    • Je me suis posé la question si je devais pas passer l’Arduino en 3.3 mais il semble que ce ne soit pas nécessaire. Peut être que les experts confirmeront (ou pas)

      The Raspberry Pi is running at 3.3 Volts while the Arduino is running at 5 Volts. There are tutorials suggest using a level converter for the I2C communication. This is NOT needed if the Raspberry Pi is running as “master” and the Arduino is running as “slave”.

      The reason it works is because the Arduino does not have any pull-ups resistors installed, but the P1 header on the Raspberry Pi has 1k8 ohms resistors to the 3.3 volts power rail. Data is transmitted by pulling the lines to 0v, for a “high” logic signal. For “low” logic signal, it’s pulled up to the supply rail voltage level. Because there is no pull-up resistors in the Arduino and because 3.3 volts is within the “low” logic level range for the Arduino everything works as it should.

  • Effectivement : si l’Arduino est en maître, il enverra du 5V et là le RPI va avoir très mal.
    Dans le sketch de l’Arduino, il manque le +1 pour le tuto. Toujours sur l’Arduino, il est formellement déconseillé de faire un Serial.print dans une interruption : ce qui est le cas (être dans une interruption) dans receiveData et dans sendData => ça peut complétement foirer le programme et « planter » l’Arduino. Les connecteurs I²C sont également dispo de l’autre côté de l’Arduino, juste après GND et AREF (c’est écrit en dessous de l’Arduino Uno).
    Pourquoi ne pas gérer également par interruption côté RPI ? (plutôt que le sleep d’une seconde qui est tout moche) C’est python qui ne le permet pas ?

    • Tuto corrigé, merci.
      Merci pour tous ces bons conseils. Je ne connais pas assez l’Arduino pour maitriser tout ça. Le but du tuto est de relier les deux et de m’en servir comme base pour la suite. Merci beaucoup pour les infos, je vais regarder comment remplacer le sleep tout moche 🙂
      La prochaine étape sera d’avoir une liaison sans fil donc au revoir I2C 😉

  • Julien

    Attention, sur le schema, le raccordement SDA et SCL est inversé !

  • Paul

    Bonjour,
    Je suis en classe de terminale sti2D et nous avons un projet pour le bac qui consiste à fabriquer une caméra de vidéosurveillance pouvant être contrôlée à distance (système android par exemple) et pouvant réaliser un TILT/PAN.
    Nous pensions donc relier Arduino et Raspberry via I²C suivant votre méthode.
    Le problème c’est que nous ne savons pas comment faire pour commander les 2 servomoteurs permettant de faire bouger la caméra….
    Une aide de votre part ne serait pas de refus 😉
    Merci

  • Raspbian

    Bonjour ,
    Premierement super tuto merci 🙂

    J’ai cependant une petite question,
    je recois plusieurs valeurs sur mon arduino est t’il possible d’envoyer les 2 valeurs en même temps sur le bus i2c ?
    Merci

  • Thibault

    Bonjour, d’après certains site il faudrait utiliser un convertisseur entre l’arduino et le raspberry car l’ un travaillerait en 5v et l’autre en 3v.
    Est ce le cas ?

  • Thibault

    Désolé je n’avais pas lu les précédents commentaires. Apparemment pas besoin.

    Parcontre quand je fais un i2cdetect je n’ai pas qu’un chiffre dans le « tableau » mais j’ai tous qui est remplis. Et l’arduino pe renvoie 0 et l’arduino affiche comme donnée reçu -1

    • Cela va venir soit d’un probleme de cablage soit d’un bug du module si les modules pour le protocle 1-wire sont chargés (w1-gpio, w1-xxxx)

  • Jody

    Bonjour,

    merci beaucoup ça fonctionne !

    Pour info si vous obtenez comme moi :

    root@raspberrypi:/home/pi# python testI2c.py
    Envoi de la valeur 3
    Traceback (most recent call last):
      File "testI2c.py", line 9, in 
        bus.write_byte(address, 3)
    IOError: [Errno 5] Input/output error
    

    Pensez à changer :

    bus = smbus.SMBus(0)

    en

    bus = smbus.SMBus(1)
    • Oui le 0 est pour le modele A et le B revison 1. Le 1 est pour le modele B revison 2

  • Ilaam

    Bonjour,
    Merci pour le tuto 🙂
    Je voudrais connecter un RPI à une autre plaque électronique (non commercialisée) en I2C avec le RPI en mode esclave. Je voudrais aussi que le RPI communique avec le maitre à chaque fois avec une adresse différente selon l’adresse que demande le maitre. Est-ce qu’il est possible d’attribuer au RPI plusieurs adresses?
    Merci

    • Sur le principe de l’I2C un périphérique ne peut pas avoir 2 adresses. Dans la programmation i2c je suis pas expert 😉

      • Ilaam

        D’accord merci pour votre réponse 🙂

  • Ilaam

    Bonjour,
    Je me retourne vers vous de nouveau.
    Voilà, j’ai lu sur un tuto que la RPi ne peut communiquer qu’en mode maitre parce que le noyau linux ne permet pas la communication en mode esclave (c’est pas encore implémenté). Est-ce que vous pourriez me confirmer si cela est vrai ? merci.

    • Oui c’est ce qui semble etre le cas. Le noyau en lui même ne supporte pas le mode esclave. Et même un driver ne devrait pas pouvoir résoudre le problème à cause du chipset utilisé sur le Raspberry (BCM 2835)

      • Ilaam

        Ah c’est dommage ! Je pense que je me servirai plutôt d’un Arduino dans ce cas. Merci bien 🙂

  • Bonjour les amis comment sont,J'ai besoin d'un programme pour se connecter à un Arduino avec framboise pi qui, à travers le port série manadar 2 différents signes qui mesurent la température et le Ph mesure un autre, Mode d'emploi???? pourriez-vous s'il vous plaît aider moi urgent. est un projet du U je suis confus sur la façon de faire.

    • Hello,
      You have an example in the post. You can use it to define your own protocol to communicate a data structure. Up to you to know how to get sensors values from the Arduino.

  • Pingback: C’est pour bientôt | La caverne de Zragg()