aide pour transformer un code

bonjour

j'ai une connection i2c entre un arduino uno rev 3 (slave) et un rapsberry (master)

après plusieurs lectures, j 'ai compilé un code mais cela ne fonctionne pas car j'ai compris qu'il me fallait passer les valeurs en float, j'ai trouvé comment faire la conversion mais je bloque pour le passage de mes valeurs vers un script python.

J'ai trouvé ArduPi-I2C-DataType-CodeArduino — MCHobby - Wiki
mais c'est trop technique pour moi. je comprends le principe mais je n'arrive pas à l'appliquer à mon
cas .

j'aimerais faire 3 envois séparés selon les valeurs température, humidité et c02 afin de les récupérer et les transmettre dans une base mysql.
Dans le script mchobby, ils envoient un exemple 5.67. j'aurais aimé passer mes 3 valeurs en mettant une variable à la place de la constante valeurDouble = 5.67; mais je n'y arrive pas.

si vous pouviez m'éclairer...

merci

#include "DHT.h"

#include <Wire.h>

#define DHTPIN 2     // what pin  DTH11 is connected to 2

// Uncomment whatever type you're using!

#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);
/*
VEETECH CO2 Monitor and Data Logger
SKETCH 2 Operation 
Code by Martin Liddament

Used to determine:
- CO2 Concentration;
IMPORTANT

- For demonstration only;
- Not verified or guaranteed free of errors;
- Not suitable for critical applications;
- Use of this code is entirely at user's risk;
- Accurate calibration of the CO2 module is essential.

This code is in the public domain.
Copyright VEETECH Ltd 2013 www.veetech.co.uk.

*/

int co2 = 9999; // co2 is the co2 concentration. Preset value for code checking


int analogPin = A0; // voltage input from sensor

// Setting Sensor Calibration Constants

 float v400ppm = 4.535;   //MUST BE SET ACCORDING TO CALIBRATION
 float v40000ppm = 3.206; //MUST BE SET ACCORDING TO CALIBRATION````````````````````````
 float deltavs = v400ppm - v40000ppm;
 float A = deltavs/(log10(400) - log10(40000));
 float B = log10(400);

void setup() {
  Wire.begin(4); // join i2c bus (address optional for master)
  
  pinMode(analogPin, INPUT); //voltage MG811 From A0
 
  dht.begin();
  Serial.begin(9600);
}


void loop() {
  
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong! end transmission
  
   if (isnan(t) || isnan(h)) {
    
    Wire.endTransmission();    // stop transmitting
   
      } else {
  
  
  // Read co2 data from sensor MG811
  
  int data = analogRead(analogPin); //digitise output from c02 sensor
  float voltage = data/204.6;       //convert output to voltage

// Calculate co2 from log10 formula (see sensor MG811 datasheet)

  float power = ((voltage - v400ppm)/A) + B;
  float co2ppm = pow(10,power);
  co2 = co2ppm;

  
  // array of values of sensors on solar room
  float Solar[3];
  float valeurSolar;
  int z=0;
  
  Solar[0]=h;
  Solar[1]=t;
  Solar[2]=co2;
  
    for (z=0;z<3;z++) {
       valeurSolar=Solar[z];
       Serial.print ("valeur");
      Serial.print (valeurSolar);
       
       //call function wire_senddouble
       
       Wire_SendDouble((double*)&valeurSolar);
      
       delay(500); 
    }
     
      
  // Wire.endTransmission();    // stop transmitting
   
      }
}
// Function for build a double vaiable in array of Bytes 
// and send data on bus I2C
//
// Based on code :
//http://arduino103.blogspot.fr/2013/08/transmettre-un-floatdouble-par-i2c.html
//http://stackoverflow.com/questions/12664826/sending-float-type-data-from-arduino-to-python
void Wire_SendDouble( double* d){
  
    // cut two types of diffeent data on the same stack of memory 
    union Sharedblock
    {
        byte part[4]; // use char parts[4] for serial port
        double data;

    } block;
    
    block.data = *d;
    
    /* 
    example for 
      block.data = 5.67
      the array part[x] is
      block.part[0] = 164;
      block.part[1] = 112;
      part[2] = 181;
      part[3] = 64;
      
    This values must be the same on the other side of BUS I2C
    */
        
    Wire.write( block.part, 4 );
}

][code]

[/code]

Dans le code que tu donnes il n'envoie pas 5.67. Il envoie le contenu de la variable passée en argument à la fonction

void Wire_SendDouble( double* d){
..
       block.data = *d;  // <---- c'est ça qui est envoyé

Le 5.67 auquel tu fais référence est dans un commentaire

merci pour la réponse

si je reprends leur code (mis en dernier dans le post) et c'est là que je suis un peu perdu, celui du post précédent c'est mon code modifié.... :roll_eyes:

à l'appel de la fonction Wire.onRequest(requestEvent) dans void setup, on va à void requestEvent() et dans le cas du registre
ou case 0x02: // Retourne un Float
valeurDouble = 5.67;

J'ai du mal exprimé ma demande...j'aimerais justement passer en paramètres mes valeurs de capteurs du genre effectivement
valeurDouble=h ou t ou c02 mais je n'arrive pas à voir comment. si j'ai bien compris l'appel dans void setup ne se fait qu'une fois or mes valeurs serait à envoyer régulièrement. je pense que cela doit se faire dans la boucle loop non?? C'est pourquoi j'avais commencé à faire un tableau avec mes valeurs et envoyer le résultat après décomposition par la fonction unionshared block ...

 // array of values of sensors on solar room
  float Solar[3];
  float valeurSolar;
  int z=0;
  
  Solar[0]=h;
  Solar[1]=t;
  Solar[2]=co2;
  
    for (z=0;z<3;z++) {
       valeurSolar=Solar[z];
       Serial.print ("valeur");
      Serial.print (valeurSolar);
 // === ArduPi-I2C ================================================
// Communication entre Arduino et Raspberry Pi via le BUS I2C
// ===============================================================
// Tutoriel: http://mchobby.be/wiki/index.php?title=ArduPi-I2C
//
// Programme Esclave qui Recoit les demandes envoyées par Raspberry Pi
// Le but étant de tester la transmission de type de données entre 
//    Arduino et Raspberry.
// S'utilise avec le programme Arduino MasterWriterDataTypes.py
//
// Ce programme attend des instructions dans le registre de commande
// registre 0x00: registre d'exécution (commande a exécuter)
//    commande 0x00 - nop
//    Commande 0x01 - demande de numero de version (retourne un byte)
//    Commande 0x02 - Retourne un Float avec la valeur 5.67
//    Commande 0x03 - 
// registre 0x01: opérant 1 - non utilisé dans cet exemple 
// registre 0x02: opérant 2 - non utilisé dans cet exemple
//
// Ecrit par D. Meurisse pour MCHobby.be
// www.mchobby.be - Vente de kit et composant Arduino et Raspberry Pi
// Licence CC-BY-SA
//
// Basé sur l'exemple de Nicholas Zambetti <http://www.zambetti.com>
//
#include <Wire.h>

// déclaration des registres
byte regs[3]; 
int regIndex = 0; // Registre à lire ou à écrire.

// copie de la dernière instruction d execution écrite dans
// le registre reg0 pour le traitement asynchrone de
// requestEvent (demande de bytes) 
byte lastExecReq = 0x00; 

void setup()
{
  // Initialisation des registres
  regs[0] = 0x00; // reg0 = registre d'exécution
                  // valeur 0x00 = NOP - No Operation = rien à faire 
  regs[1] = 0x00; 
  regs[2] = 0x00;
  
  // Joindre le Bus I2C avec adresse #4
  Wire.begin(4);
  // enregistrer l'événement 
  //    Lorsque des données sont écrites par le maitre et reçue par l'esclave
  Wire.onReceive(receiveEvent); 
  // enregistrer l'événement 
  //    Lorsque le Maitre demande de lecture de bytes
  Wire.onRequest(requestEvent); 
  
  // Démarrer une communication série
  Serial.begin(19200);           
  Serial.println( F("Bus I2C pret") );
  
  // Definir la broche 13 en sortie
  pinMode( 13, OUTPUT );
  digitalWrite( 13, HIGH );
}

void loop()
{
  // Si NOP alors rien à faire
  if( regs[0] == 0x00 ) {
    delay(100);
    return;
  }
  
  // Exécution de l'opération
  /* Serial.println( F("--- Traitement Requete ---") );
  Serial.print( F("reg0 = ") );
  Serial.println( regs[0], DEC );
  Serial.print( F("reg1 = ") );
  Serial.println( regs[1], DEC );
  Serial.print( F("reg2 = ") );
  Serial.println( regs[2], DEC );
  */
 
  switch( regs[0] ){
    case 0x01 : // demande de version (rien à faire)
      break;
    case 0x02 : // demande de valeur Float (rien à faire, l'operation et retour de donnée est exécuté à la demande de réponse)
      break;
    /* Issu d'un autre exemple 
    
    case 0x03 : // Activer/désactiver Pin 13 en fct de la valeur du registre 0x01
      if( regs[1] > 0 )
         digitalWrite( 13, HIGH );
      else
         digitalWrite( 13, LOW ); 
      break;
    */
  } 

  // reset to NOP
  regs[0] = 0x00;  
}

// Fonction qui est exécutée lorsque des données sont envoyées par le Maître.
// Cette fonction est enregistrée comme une événement ("event" en anglais), voir la fonction setup()
void receiveEvent(int howMany)
{
  int byteCounter = 0;
 
  // Pour faire du debug... mais attention cela peut planter
  //    la réception!
  //
  //Serial.println(F("---- LECTURE ---"));
  //Serial.print(F("Numbre de Bytes: "));
  //Serial.println( howMany );

  // Lire tous les octets sauf le dernier
  while( byteCounter < howMany ) 
  {
    // lecture de l'octet
    byte b = Wire.read();     
    byteCounter += 1;
    
    //Serial.println( b, DEC );
     
    if( byteCounter == 1 ){   // Byte #1 = Numéro de registre
       regIndex = b;
    } 
    else {                    // Byte #2 = Valeur a stocker dans le registre
       switch(regIndex) {
         case 0:
           regs[0] = b;
           // maintenir une copie du dernier reg0 pour 
           // traitement d'une réponse via requestEvent (demande de byte)
           lastExecReq = b; 
           break;
         case 1: 
           regs[1] = b;
           break;
         case 2:
           regs[2] = b;
           break;   
       } 
    }
    
    
  } // fin WHILE
}


// Fonction outil décomposant un double en array de Bytes 
// et envoyant les données sur le bus I2C
//
// Basé sur le code obtenu ici:
//      http://stackoverflow.com/questions/12664826/sending-float-type-data-from-arduino-to-python
void Wire_SendDouble( double* d){
  
    // Permet de partager deux types distinct sur un meme espace
    // memoire
    union Sharedblock
    {
        byte part[4]; // utiliser char parts[4] pour port série
        double data;

    } mon_block;
    
    mon_block.data = *d;
    
    /* 
    pour... 
      mon_block.data = 5.67
    le tableau part[x] vaut...
      mon_block.part[0] = 164;
      mon_block.part[1] = 112;
      mon_block.part[2] = 181;
      mon_block.part[3] = 64;
      
    Ce sont les valeurs que l'on doit retrouver de l'autre cote du BUS I2C
    */
        
    Wire.write( mon_block.part, 4 );
}

double valeurDouble;

// Fonction est activé lorsque le Maitre fait une demande de lecture.
// 
void requestEvent()
{
  // Deboggage - Activer les lignes suivantes peut perturber fortement 
  //    l'échange I2C... a utiliser avec circonspection.
  //
  //   Serial.print( "Lecture registre: " );
  //   Serial.println( regIndex );
  
  // Quel registre est-il lu???
  switch( regIndex ){ 
 
    case 0x00: // lecture registre 0 
          // la réponse depend de la dernière opération d'exécution demandée 
          //    par l'intermédiaire du registre d'exécution (reg 0x00).
          switch( lastExecReq ) {
            case 0x01: // demande de version
              // current version = v3
              Wire.write( 0x11 ); 
              break;
              
            case 0x02: // Retourne un Float
              valeurDouble = 5.67;   
              // essayer aussi avec 
              //    valeurDouble = 128.1245;

              // Décompose la valeur en Bytes et l'envoi sur I2C
              Wire_SendDouble( &valeurDouble );
              break;
          
            default:
              Wire.write( 0xFF ); // ecrire 255 = il y a un problème! 
          }
          break;
     
    default: // lecture autre registre 
      Wire.write( 0xFF ); // ecrire 255 = il y a un problème
  }  
  
}

Faut lire les docs Wire - Arduino Reference

Wire.onRequest: cette fonction déclare une fonction qui sera appelée à chaque fois que le maître fait une demande de lecture.

requestEvent : cette fonction est donc appelée à chaque fois que le maître demande une lecture du périphérique I²C (l'arduino donc). La variable lastExecReq contient le numéro de l'opération à effectuer:
// commande 0x00 - nop
// Commande 0x01 - demande de numero de version (retourne un byte)
// Commande 0x02 - Retourne un Float avec la valeur 5.67
// Commande 0x03 -

Si tu veux que ton arduino retourne le CO2 pour la commande 02 tu remplaces 5.67 par le nom de la variable que tu veux envoyer.
Ensuite tu peux ajouter d'autre "commande" une commande 03 pour la température, une commande 04 pour la température, ..

en en relisant le code une enième fois, corrigez moi si je suis bien le fonctionnement.

le master demande par un write 0x02 un event a l'arduino
le slave traite la demande en incrementant un compteur pour parcourir les données envoyées par le master
je ne compends plus à ce moment le script

une fois ce traitement effectué, on part sur le on request ou là est envoyé la valeur après traitement par unionshared block
donc si je mets dans un registe une aute commande style 002>envoie float1;(sensor1) 003 >envoi float2(sensor2), je pourais envoyé mes valeurs de capteurs.

est un bon raisonnement ? qui pourrais m'expliquer alors la partie du code

void receiveEvent(int howMany)
{
  int byteCounter = 0;
 
  // Pour faire du debug... mais attention cela peut planter
  //    la réception!
  //
  //Serial.println(F("---- LECTURE ---"));
  //Serial.print(F("Numbre de Bytes: "));
  //Serial.println( howMany );

  // Lire tous les octets sauf le dernier
  while( byteCounter < howMany ) 
  {
    // lecture de l'octet
    byte b = Wire.read();     
    byteCounter += 1;
    
    //Serial.println( b, DEC );
     
    if( byteCounter == 1 ){   // Byte #1 = Numéro de registre
       regIndex = b;
    } 
    else {                    // Byte #2 = Valeur a stocker dans le registre
       switch(regIndex) {
         case 0:
           regs[0] = b;
           // maintenir une copie du dernier reg0 pour 
           // traitement d'une réponse via requestEvent (demande de byte)
           lastExecReq = b; 
           break;
         case 1: 
           regs[1] = b;
           break;
         case 2:
           regs[2] = b;
           break;   
       } 
    }

merci

:slight_smile:

on a posté au m^me instant donc mon raisonnement est bon :smiley: le métier rentre je commence à comprendre le cheminement

peut tu m'expliquer le code comptant les octets reçus. le fait que les variables sont calculées dans la boucle loop et qu'on y fait référence dans la partie setup n'est pas un problème

void receiveEvent(int howMany)
{
  int byteCounter = 0;
 
  // Pour faire du debug... mais attention cela peut planter
  //    la réception!
  //
  //Serial.println(F("---- LECTURE ---"));
  //Serial.print(F("Numbre de Bytes: "));
  //Serial.println( howMany );

  // Lire tous les octets sauf le dernier
  while( byteCounter < howMany ) 
  {
    // lecture de l'octet
    byte b = Wire.read();     
    byteCounter += 1;

Ce code c'est la réception des commandes. Cela correspond à ce qui est décrit dans ces commentaires
// registre 0x00: registre d'exécution (commande a exécuter)
//....
// registre 0x01: opérant 1 - non utilisé dans cet exemple
// registre 0x02: opérant 2 - non utilisé dans cet exemple

Avant tout il faut comprendre comment fonctionne l'I²C.
Le premier octet transmis c'est l'adresse du registre dans lequel on veut écrire.
Ensuite on envoie les données à écrire.
Après chaque écriture l'adresse du registre avance automatiquement.

C'est ce que fait receiveEvent.

merci je comprends mieux. je vais relire les tutos sur l2c car j'ai oublié le coup de la tame :wink:

bonne soirée

et encore merci

hello

j'ai modifié le code avec les commandes comme indiqué par fdufnews. est ce correct?

j'ai une erreur
[0,0,4,66]
line 70, in module
h_data, = struct.unpack('f', sData)

struct.error unpack requires a string argument of lengh 4. est ce lié au 0,0 du tableau de résultat ? dans ce cas comment avoir la bonne transformation? :cold_sweat:
si je comprends :grin: le code le 0,0,4, 66 passe par la "sous fonction unpack" qui remet par ordre reçu en type float.le 0, 0 n'est pas compris?

merci

#!/usr/bin/env python
# -*- coding: latin-1 -*-

# === ArduPi-I2C ================================================
# Communication entre Arduino et Raspberry Pi via le BUS I2C
# ===============================================================
# Tutoriel: http://mchobby.be/wiki/index.php?title=ArduPi-I2C
#  
# Programme Master qui envoi des instructions vers un Arduino par 
# l'intermédiaire de "registres" de façon logiciel sur Arduino. 
# S'utilise avec le programme Arduino SlaveRegisterDataTypes.ino
#
# Ecrit par D. Meurisse pour MCHobby.be
# www.mchobby.be - Vente de kit et composant Arduino et Raspberry Pi
# Licence CC-BY-SA
#
# Basé sur Adafruit_I2C.py librairie Python écrite par AdaFruit Industries 
# www.adafruit.com

import time
import struct
from Adafruit_I2C import Adafruit_I2C
import MySQLdb

from time import sleep, gmtime, strftime

import smtplib
import os
import sys
import smtplib                         

i2c = Adafruit_I2C( 0x04 )

db = MySQLdb.connect(host="localhost",user="root",passwd="poi",db="db_rheorthe")
con = db.cursor()

   
date_mesure = strftime("%Y-%m-%d %H:%M:%S.000", gmtime())
   

# --- Demander le NO de version ---
# Transfert d'un type BYTE

# Ecriture de la valeur 0x01 dans le registre 0 
i2c.write8( 0, 0x01 );
time.sleep( 0.020 );
print( i2c.readU8( 0x00 ) );

# Donner un delai au périphérique I2C pour qu'il soit prêt a recevoir
# une nouvelle communication... sinon on recoit l'erreur
#   Error accessing 0x04: Check your I2C address
time.sleep( 0.100 )

# --- Demander une valeur décimale ---
# Transfert d'un type DOUBLE

# demander l'opération de reception d'un float h humidité, placer 0x02 dans le
# le registre d'exécution 0
i2c.write8( 0x00, 0x02 )
time.sleep(0.100)
i2c.debug = True


# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
        sData = sData + chr(aByte)

        h_data, = struct.unpack('<f',sData)
        #print h_data # Affiche la valeur en Float.

        # INSERT de la mesure
        sql_command = "INSERT INTO tbl_Temp_Ext (Capteur,Humidite,Date_Mesure) VALUES('"+SOLAR_TH+"', "+h_data+", '"+date_mesure+"');"
        con=execute(sql_command)
        db.commit

                    
# demander l'opération de reception d'un float t temperature, placer 0x03 dans le
# le registre d'exécution 0
i2c.write8( 0x00, 0x03 )
time.sleep(0.100)
i2c.debug = True

# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
        sData = sData + chr(aByte)

        t_data, = struct.unpack('<f',sData)
        print t_data # Affiche la valeur en Float.

        # INSERT de la mesure
        sql_command = "INSERT INTO tbl_Temp_Ext (Capteur,Temperature,Date_Mesure) VALUES('"+SOLAR_TH+"', "+t_data+", '"+date_mesure+"');"
        con=execute(sql_command)
        db.commit
                        
# demander l'opération de reception d'un float c02, placer 0x04 dans le
# le registre d'exécution 0
i2c.write8( 0x00, 0x04 )
time.sleep(0.100)
i2c.debug = True

# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
    sData = sData + chr(aByte)

    co2_data, = struct.unpack('<f',sData)
    print co2_data # Affiche la valeur en Float.

    # INSERT de la mesure
    sql_command = "INSERT INTO tbl_Solar_Co2 VALUES('"+SOLAR_CO2+"', "+Taux_co2+", '"+date_mesure+"');"

    con=execute(sql_command)
    db.commit

if (mysql_errno()) :
    sendTextMail()
    db.rollback()
                      

    
con.close()
db.close() 
...

Des erreurs d'indentation.
ATTENTION, en python l'indentation est très importante. C'est elle qui détermine les blocs de code.

# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
        sData = sData + chr(aByte)

        t_data, = struct.unpack('<f',sData)
        print t_data # Affiche la valeur en Float.

        # INSERT de la mesure
        sql_command = "INSERT INTO tbl_Temp_Ext (Capteur,Temperature,Date_Mesure) VALUES('"+SOLAR_TH+"', "+t_data+", '"+date_mesure+"');"
        con=execute(sql_command)
        db.commit

Toutes les lignes qui ont la même indentation forment un bloc de code. Dans le cas ci-dessus toutes les lignes sont exécutées dans le for.
Je pense que le code correct devrait être comme ça.

# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
        sData = sData + chr(aByte)

t_data, = struct.unpack('<f',sData)
print t_data # Affiche la valeur en Float.

# INSERT de la mesure
sql_command = "INSERT INTO tbl_Temp_Ext (Capteur,Temperature,Date_Mesure) VALUES('"+SOLAR_TH+"', "+t_data+", '"+date_mesure+"');"
con=execute(sql_command)
db.commit

Faire la même chose dans le for situé juste sous celui-ci.

ok merci

je vais travailler cela. pour l'erreur sur le unpack, tu aurais une piste?

merci

merci pour cette partie, c'est lié effectivement au différent décalage dans la syntaxe. les cas différents de registre ont l'air de fonctionner. j'ai d'autres messages d'erreur mais je fait un autre post pour ceux ci.

voilà les codes pour info

python

#!/usr/bin/env python
# -*- coding: latin-1 -*-

# === ArduPi-I2C ================================================
# Communication entre Arduino et Raspberry Pi via le BUS I2C
# ===============================================================
# Tutoriel: http://mchobby.be/wiki/index.php?title=ArduPi-I2C
#  

# Ecrit par D. Meurisse pour MCHobby.be
# www.mchobby.be - Vente de kit et composant Arduino et Raspberry Pi
# Licence CC-BY-SA
#
# Basé sur Adafruit_I2C.py librairie Python écrite par AdaFruit Industries 
# www.adafruit.com

import time
import struct
from Adafruit_I2C import Adafruit_I2C
import MySQLdb

from time import sleep, gmtime, strftime

import smtplib
import os
import sys
import smtplib                         

i2c = Adafruit_I2C( 0x04 )

db = MySQLdb.connect(host="localhost",user="root",passwd="xxx",db="xxx")
con = db.cursor()

   
date_mesure = strftime("%Y-%m-%d %H:%M:%S", gmtime())
print date_mesure   

# --- Demander le NO de version ---
# Transfert d'un type BYTE

# Ecriture de la valeur 0x01 dans le registre 0 
i2c.write8( 0, 0x01 );
time.sleep( 0.020 );
print( i2c.readU8( 0x00 ) );

# Donner un delai au périphérique I2C pour qu'il soit prêt a recevoir
# une nouvelle communication... sinon on recoit l'erreur
#   Error accessing 0x04: Check your I2C address
time.sleep( 0.100 )

# --- Demander une valeur décimale ---
# Transfert d'un type DOUBLE

# demander l'opération de reception d'un float h humidité, placer 0x02 dans le
# le registre d'exécution 0
i2c.write8( 0x00, 0x02 )
time.sleep(0.100)
i2c.debug = True


# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
        sData = sData + chr(aByte)


h_data=struct.unpack('<f',sData)
print h_data # Affiche la valeur en Float.
#h_data_i=round(h_data,2)
#print h_data_i



capteur_ht='SOLAR_H'
# INSERT de la mesure
sql_command = "INSERT INTO tbl_Solar_Hum (Capteur,Humidite, Date_Mesure) VALUES('capteur_ht', 'h_data', 'date_mesure');"
con.execute(sql_command)
db.commit

                    
# demander l'opération de reception d'un float t temperature, placer 0x03 dans le
# le registre d'exécution 0
i2c.write8( 0x00, 0x03 )
time.sleep(0.100)
i2c.debug = True

# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
        sData = sData + chr(aByte)

t_data, = struct.unpack('<f',sData)
print t_data # Affiche la valeur en Float.

capteur_ht='SOLAR_T'
# INSERT de la mesure
sql_command = "INSERT INTO tbl_Solar_Temp (Capteur, Temperature,Date_Mesure) VALUES('capteur_ht', 't_data', 'date_mesure');"
con.execute(sql_command)
db.commit
                        
# demander l'opération de reception d'un float c02, placer 0x04 dans le
# le registre d'exécution 0
i2c.write8( 0x00, 0x04 )
time.sleep(0.100)
i2c.debug = True

# transformer en string pour unpack
lstData=i2c.readList(0x00,4)
sData = ''
for aByte in lstData:
    sData = sData + chr(aByte)

co2_data, = struct.unpack('<f',sData)
print co2_data # Affiche la valeur en Float.

capteur_co2='SOLAR_CO2'
# INSERT de la mesure
sql_command = "INSERT INTO tbl_Solar_Co2 (Capteur,Taux_co2,Date_Mesure) VALUES('capteur_co2', 'Taux_co2', 'date_mesure');"

con.execute(sql_command)
db.commit

if mysql_errno() :
    
    db.rollback()

code arduino

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain
 // === ArduPi-I2C ================================================
// Communication entre Arduino et Raspberry Pi via le BUS I2C
// ===============================================================
// Tutoriel: http://mchobby.be/wiki/index.php?title=ArduPi-I2C
//
// Programme Esclave qui Recoit les demandes envoyées par Raspberry Pi
// // S'utilise avec le programme Arduino MasterWriterDataTypes.py
//
// Ce programme attend des instructions dans le registre de commande
// registre 0x00: registre d'exécution (commande a exécuter)
//    commande 0x00 - nop
//    Commande 0x01 - demande de numero de version (retourne un byte)
//    Commande 0x02 - Retourne un Float avec la valeur h
//    Commande 0x03 - Retourne un Float avec la valeur t
//    Commande 0x04 - Retourne un Float avec la valeur co2
// registre 0x01: opérant 1 - non utilisé dans cet exemple 
// registre 0x02: opérant 2 - non utilisé dans cet exemple
//
// Ecrit par D. Meurisse pour MCHobby.be
// www.mchobby.be - Vente de kit et composant Arduino et Raspberry Pi
//
// Basé sur l'exemple de Nicholas Zambetti <http://www.zambetti.com>

#include "DHT.h"

#include <Wire.h>

float h;
float t;
double valeurDouble;


// déclaration des registres
byte regs[3]; 
int regIndex = 0; // Registre à lire ou à écrire.

// copie de la dernière instruction d execution écrite dans
// le registre reg0 pour le traitement asynchrone de
// requestEvent (demande de bytes) 
byte lastExecReq = 0x00; 


#define DHTPIN 2     // what pin  DTH11 is connected to 2

// Uncomment whatever type you're using!

#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);
/*
VEETECH CO2 Monitor and Data Logger
SKETCH 2 Operation 
Code by Martin Liddament

Used to determine:
- CO2 Concentration;
IMPORTANT

this code is in the public domain.
Copyright VEETECH Ltd 2013 www.veetech.co.uk.

*/

float co2 = 9999; // co2 is the co2 concentration. Preset value for code checking


int analogPin = A0; // voltage input from sensor

// Setting Sensor Calibration Constants

 float v400ppm = 4.535;   //MUST BE SET ACCORDING TO CALIBRATION
 float v40000ppm = 3.206; //MUST BE SET ACCORDING TO CALIBRATION````````````````````````
 float deltavs = v400ppm - v40000ppm;
 float A = deltavs/(log10(400) - log10(40000));
 float B = log10(400);

void setup() {
  
  // Initialisation des registres
  regs[0] = 0x00; // reg0 = registre d'exécution
                  // valeur 0x00 = NOP - No Operation = rien à faire 
  regs[1] = 0x00; 
  regs[2] = 0x00;
  Wire.begin(4); // join i2c bus (address optional for master)
  
  pinMode(analogPin, INPUT); //voltage MG811 From A0
 
  dht.begin();
    
  Serial.begin(9600);
  
  // enregistrer l'événement 
  //    Lorsque des données sont écrites par le maitre et reçue par l'esclave
  Wire.onReceive(receiveEvent);
 // enregistrer l'événement 
  //    Lorsque le Maitre demande la lecture de bytes
  Wire.onRequest(requestEvent);
  
}


void loop() {
  
  
  // Si NOP alors rien à faire
  if( regs[0] == 0x00 ) {
    delay(100);
    return;
  }
  
  // Exécution de l'opération
  /* Serial.println( F("--- Traitement Requete ---") );
  Serial.print( F("reg0 = ") );
  Serial.println( regs[0], DEC );
  Serial.print( F("reg1 = ") );
  Serial.println( regs[1], DEC );
  Serial.print( F("reg2 = ") );
  Serial.println( regs[2], DEC );
  */
 
  switch( regs[0] ){
    case 0x01 : // demande de version (rien à faire)
      break;
    case 0x02 : // demande de valeur Float temperature (rien à faire, l'operation et retour de donnée est exécuté à la demande de réponse)
      break;
    
     
    case 0x03 : // demande de valeur Float humidité (rien à faire, l'operation et retour de donnée est exécuté à la demande de réponse)
      break;
        
    
    case  0x04 :// demande de valeur Float co2(rien à faire, l'operation et retour de donnée est exécuté à la demande de réponse)
      break;
        
  } 

  // reset to NOP
  regs[0] = 0x00;
  
  
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
 h = dht.readHumidity();
 t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong! end transmission
  
   if (isnan(t) || isnan(h)) {
    
    Wire.endTransmission();    // stop transmitting
   
      } else {
  
  
  // Read co2 data from sensor MG811
  
  int data = analogRead(analogPin); //digitise output from c02 sensor
  float voltage = data/204.6;       //convert output to voltage

// Calculate co2 from log10 formula (see sensor MG811 datasheet)

  float power = ((voltage - v400ppm)/A) + B;
  float co2ppm = pow(10,power);
  co2 = co2ppm;

  Serial.println(h);
  Serial.println(t);
  Serial.println(co2);
   
      }
}
// Function for build a double vaiable in array of Bytes 
// and send data on bus I2C
//
// Based on code :
//http://arduino103.blogspot.fr/2013/08/transmettre-un-floatdouble-par-i2c.html
//http://stackoverflow.com/questions/12664826/sending-float-type-data-from-arduino-to-python
void Wire_SendDouble( double* d){
  
    // cut two types of diffeent data on the same stack of memory 
    union Sharedblock
    {
        byte part[4]; // use char parts[4] for serial port
        double data;

    } block;
    
    block.data = *d;
    
    /* 
    example for 
      block.data = 5.67
      the array part[x] is
      block.part[0] = 164;
      block.part[1] = 112;
      part[2] = 181;
      part[3] = 64;
      
    This values must be the same on the other side of BUS I2C
    */
        
    Wire.write( block.part, 4 );
}

// Fonction qui est exécutée lorsque des données sont envoyées par le Maître.
// Cette fonction est enregistrée comme une événement ("event" en anglais), voir la fonction setup()
void receiveEvent(int howMany)
{
  int byteCounter = 0;
 
  // Pour faire du debug... mais attention cela peut planter
  //    la réception!
  //
  //Serial.println(F("---- LECTURE ---"));
  //Serial.print(F("Numbre de Bytes: "));
  //Serial.println( howMany );

  // Lire tous les octets sauf le dernier
  while( byteCounter < howMany ) 
  {
    // lecture de l'octet
    byte b = Wire.read();     
    byteCounter += 1;
    
    //Serial.println( b, DEC );
     
    if( byteCounter == 1 ){   // Byte #1 = Numéro de registre
       regIndex = b;
    } 
    else {                    // Byte #2 = Valeur a stocker dans le registre
       switch(regIndex) {
         case 0:
           regs[0] = b;
           // maintenir une copie du dernier reg0 pour 
           // traitement d'une réponse via requestEvent (demande de byte)
           lastExecReq = b; 
           break;
         case 1: 
           regs[1] = b;
           break;
         case 2:
           regs[2] = b;
           break;   
       } 
    }
    
    
  } // fin WHILE
}


// Fonction est activé lorsque le Maitre fait une demande de lecture.
// 
void requestEvent()
{
  // Deboggage - Activer les lignes suivantes peut perturber fortement 
  //    l'échange I2C... a utiliser avec circonspection.
  //
  //   Serial.print( "Lecture registre: " );
  //   Serial.println( regIndex );
  
  // Quel registre est-il lu???
  switch( regIndex ){ 
 
    case 0x00: // lecture registre 0 
          // la réponse depend de la dernière opération d'exécution demandée 
          //    par l'intermédiaire du registre d'exécution (reg 0x00).
          switch( lastExecReq ) {
            case 0x01: // demande de version
              // current version = v3
              Wire.write( 0x11 ); 
              break;
              
            case 0x02: // Retourne un Float
              valeurDouble = h;   
              
             // Décompose la valeur en Bytes et l'envoi sur I2C
              Wire_SendDouble((double*)&valeurDouble);
              break;
              
            case 0x03: // Retourne un Float t
              valeurDouble = t;   
                           // Décompose la valeur en Bytes et l'envoi sur I2C
              Wire_SendDouble((double*)&valeurDouble);
              
              break;
              
              
              case 0x04: // Retourne un Float co2
              valeurDouble = co2; 
              Wire_SendDouble((double*)&valeurDouble);
             

                    break;
                
            default:
                              
              Wire.write( 0xFF ); // ecrire 255 = il y a un problème! 
          }
          break;
     
    default: // lecture autre registre 
      Wire.write( 0xFF ); // ecrire 255 = il y a un problème
  }  
  
}