Arduino - RPI - communication via i2C

Bonjour,

Je m’intéresse de prêt, depuis 6 mois environ, à la domotique.
J’ai déjà équipé mon chez moi d’un système d’ouverture fermeture automatique des mes volets (avec le protocole ZWAVE)ainsi qu’un pilotage de l’éclairage de mon entré / salon / cuisine.
J’ai quelques connaissance en C / C++ / Java / VB / …

Vu le prix des modules (au minimum 30€, voir 60€ pour du Zwave) j’ai commencé à “construire” mes propres modules à base d’arduino.
Et puis c’est beaucoup plus gratifiant de faire les choses soir même et comprendre comme tout ce la fonctionne concrètement.
Je commence par quelque chose de simple : un module capteur de température / humidité sans fil. Pour faire rapide je souhaiterai que les infos soient exploitées par le logiciel de domotique Jeedom.

Voici mon matériel :

  • Box domotique : un RPI 3 avec Jeedom
  • Un récepteur RF433 MHz connecté à un arduino qui lui même est connecté au RPI via les ports i2C
  • Un module fait maison avec arduino + émeteur RF433 Mhz + capteur température DHT11.

Aujourd’hui j’arrive à récupérer les info sur l’arduino récepteur mais je n’arrive pas à les récupérer sur le RPI via les ports i2c.

Voici mes programmes :

  • Pour l’éméteur (celui avec le capteur DHT11) :
#include <DHT.h>               //inclusion de la librairie dht
#include <VirtualWire.h>      // inclusion de la librairie VirtualWire
#define MESSAGE_SIZE 4    // Nombre de bytes à envoyer

//Constantes
#define DHTPIN 7               // Broche sur laquelle le capteur est câblé
#define DHTTYPE DHT11     // Type de capteur

float CODE = 12;               // Code protocole propriétaire

DHT dht(DHTPIN, DHTTYPE); // Déclaration du capteur
float P = 1;                      // 1 = cuisine, 2 = chambre 1, ...
 
void setup() {
  Serial.begin(9600);        //Lancement de la liaison série
  delay(300);                  //Temps de démarrage du système
  dht.begin();                 //Initialisation du capteur
  vw_setup(2000);          // initialisation de la librairie VirtualWire à 2000 bauds
}
 
void loop() {
  //Attente avant la prochaine mesure
  delay(1000);
  
  //Humidité
  float humidite = dht.readHumidity();
  //Température en celcius
  float tempCelcius = dht.readTemperature();
  //Température en Fahrenheit
  float tempFahr = dht.readTemperature(true);
  
  //Vérification qu'il n'y ait pas d'erreurs de lecture
  if (isnan(humidite) || isnan(tempCelcius) || isnan(tempFahr)) {
    Serial.println("Erreur de lecture du capteur DHT!");
    return;
  }
 
  // Température ressentie
  float tempRessentie = dht.computeHeatIndex(tempFahr, humidite);
  //Conversion en degrés
  tempRessentie = (tempRessentie-32.0)*(5.0/9.0);
 
  Serial.print("Humidite: "); 
  Serial.print(humidite);
  Serial.print(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(tempCelcius);
  Serial.print(" *C ");
  Serial.print("Temperature ressentie: ");
  Serial.print(tempRessentie); 
  Serial.println(" *C");

  uint8_t msg[MESSAGE_SIZE] = {0, 0, 0, 0};

  msg[0] = (uint8_t)CODE;
  msg[1] = (uint8_t)P;
  msg[2] = (uint8_t)humidite;
  msg[3] = (uint8_t)tempCelcius;

  vw_send((byte *) &msg, sizeof(msg));                // On envoie le message
  vw_wait_tx();                                       // On attend la fin de l'envoi
}

Les infos sont stockées dans un tableau à 4 dimensions et envoyées par éméteur 433Mhz :

  • Le code me servira plus tard

  • la variable P correspond à la pièce ou se trouve le capteur

  • La variable humidité

  • La variable température

  • Du coté du récepteur (l’arduino connecté en i2c au RPI) :

#include <Wire.h>
#include <VirtualWire.h>
#define MESSAGE_SIZE 4    // Nombre de bytes à recevoir

int piece = 0;
int humidite = 0;
int temperature = 0;

#define SLAVE_ADDRESS 0x12
int dataReceived = 0;

void setup() {
    Serial.begin(9600);
    Wire.begin(SLAVE_ADDRESS);
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);
    
    vw_set_rx_pin(12); // PIN sur laquelle est branché le récepteur
    
    vw_setup(2000);   // Initialisation de la bibliothèque VirtualWire
    vw_rx_start();    // On peut maintenant recevoir des messages
    }

void loop() {
    // delay(2000);
    }

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

void sendData(){

    uint8_t msg[MESSAGE_SIZE] = {0, 0, 0, 0};
    byte taille_message = sizeof(msg);

    vw_wait_rx();     // On attend de recevoir un message

    int code  = msg[0];
    Serial.println(msg[0]);
     
    if (vw_get_message((byte *) &msg, &taille_message)) {
    // On copie le message, qu'il soit corrompu ou non

        Serial.print("Code = ");
        Serial.print(msg[0]);
        Serial.print("\t");

        Serial.print("pièce = ");
        Serial.print(msg[1]);
        Serial.print("\t");
        
        Serial.print("Humidité = ");
        Serial.print(msg[2]);
        Serial.print("%\t");
        
        Serial.print("Température = ");
        Serial.print(msg[3]); 
        Serial.println(" *C");
        
        piece = msg[1];
        humidite = msg[2];
        temperature = msg[3];
        }
  
    Wire.write(piece);
    Wire.write(humidite);
    Wire.write(temperature);
}

Enfin du côté du RPI j’ai un programme en Python :

import smbus
import time

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

time.sleep(30) # Pause de 30 secondes pour laisser le temps au traitement de se faire
reponse = bus.read_byte(address)
print "La reponse de l'arduino : ", reponse

Voila, je pense qu’il y a un truc qui va pas au niveau de l’envoie des données sur le port i2c ou de la récupération via le programme python.
Je me suis demandé s’il fallait pas aussi concaténer les donnés pices/humidite/temperature dans le programme récepteur arduino pour n’envoyer qu’une variable via l’i2c.

Merci d’avance pour votre aide