[Programmation] Problème capteur CO2 (Interface E2)
Répondre à la discussion
Affichage des résultats 1 à 3 sur 3

Problème capteur CO2 (Interface E2)



  1. #1
    ELT4

    Problème capteur CO2 (Interface E2)


    ------

    Bonjour,

    Dans le cadre d'un projet, je dois analyser l'air et définir le taux de CO2 environnent. Pour cela, j'utilise un capteur EE893 communicant part interface E2 propre au fournisseur (E+E).

    Pour gérer mon projet, j'utilise un PIC18F26J50 en 3.3V configurer en clock interne à 48MHz.
    Je programme mon PIC avec MPLABX v3.20 comme IDE et CCS C v.5.042 comme compilateur (language C).

    J'ai lu deux trois dossiers sur l'interface E2 et j'ai remarqué qu'il était similaire au bus I2C. J'ai donc suivis le protocole E2Bus donné dans une datasheet du fournisseur, en utilisant l'interface I2C. J'ai réussi à obtenir de bref résultat lorsque le capteur était brancher seul sur les I/O spécifique à l'I2C (SDA:PIN_B5, SCL:PIN_B4).

    Le problème survient lorsque je branche d'autres périphériques sur ces I/O (LCD, EEPROM, RTC), tout la ligne est perturbé part le capteur. J'ai essayé plusieurs techniques mais rien n'y fait.

    Comme le capteur s'alimente en 5V et que le PIC est en 3.3V, j'ai réalisé un circuit pour convertir l'I2C du 3.3V en 5V et inversement, avec ou sans, toujours le même problème.

    Utiliser un module I2C différent en le forçant à utiliser deux autres PINs ne fonctionne pas.
    Code:
    #use i2c(MASTER, SDA=PIN_B3, SCL=PIN_B2, STREAM=E2)
    J'ai lus que le bus E2 tourne entre 500 et 5000Hz alors j'ai essayé ceci :
    Code:
    #use i2c(MASTER, FAST=500, SDA=PIN_B3, SCL=PIN_B2, STREAM=E2)
    J'ai également essayé leur driver qui semble recréer de l'I2C manuellement.

    Code:
    typedef struct st_E2_Return
    {
    unsigned char DataByte;
    unsigned char Status;
    }st_E2_Return;
    
    /***************************************************************************/
    // functions
    st_E2_Return knl_E2bus_readByteFromSlave( char ControlByte );
    int check_ack(void);
    void send_ack(void);
    void send_nak(void);
    void E2Bus_start(void); // send start condition
    void E2Bus_stop(void); // send stop condition
    void E2Bus_send(unsigned char);
    void set_SDA(void);
    void clear_SDA(void);
    int read_SDA(void);
    void set_SCL(void);
    void clear_SCL(void);
    unsigned char E2Bus_read(void); // read one byte from E2-Bus
    void delay(unsigned int value);
    unsigned int read_co2(void);
    void init_E2();
    
    /***************************************************************************/
    
    #define CB_MV3LO 0xC1 // ControlByte for reading Measurement value 3 Low-Byte
    #define CB_MV3HI 0xD1 // ControlByte for reading Measurement value 3 High-Byte
    #define E2_DEVICE_ADR 0x00 // Address of E2-Slave-Device
    #define DELAY_FAKTOR  2
    #define ACK           1
    #define NAK           0
    #define RETRYS        1 
    #define E2_SDA   PIN_B3
    #define E2_SCL   PIN_B2
    
    void init_E2()
    {
       output_float(E2_SCL);
       output_float(E2_SDA);
    }
    /*-------------------------------------------------------------------------*/
    unsigned int read_co2(void) // Read Measurement Value 3 (CO2 RAW [ppm])
    {
        struct st_E2_Return E2_Return;
        unsigned int CO2_RAW;
        unsigned int CO2_LB, CO2_HB;
        CO2_RAW = 400;
        E2_Return = knl_E2bus_readByteFromSlave(CB_MV3LO | (E2_DEVICE_ADR << 1));
        CO2_LB = E2_Return.DataByte;
        if (E2_Return.Status == 0) {
      output_high(PIN_C7);
            E2_Return = knl_E2bus_readByteFromSlave(CB_MV3HI | (E2_DEVICE_ADR << 1));
            CO2_HB = E2_Return.DataByte;
            if (E2_Return.Status == 0) {
                CO2_RAW = CO2_LB + (CO2_HB<<4);
            }
        }
        return CO2_RAW;
    }
    
    st_E2_Return knl_E2bus_readByteFromSlave(unsigned char ControlByte) // read byte from slave with controlbyte
    {
        unsigned char Checksum;
        unsigned char counter = 0;
        struct st_E2_Return E2_Return;
        E2_Return.Status = 1;
        while (E2_Return.Status && counter < RETRYS) // RETRYS...Number of read attempts
        {
            E2Bus_start(); // send E2 start condition
            E2Bus_send(ControlByte); // send 0xA1 (example for reading Temp_Low byte)
            if (check_ack() == ACK) // ACK received?
            {
                E2_Return.DataByte = E2Bus_read(); // read Temp_low (example for reading Temp_Low byte)
                send_ack(); // send ACK
                Checksum = E2Bus_read(); // read checksum
                send_nak(); // send NACK
                if (((ControlByte + E2_Return.DataByte) % 0x100) == Checksum) // checksum OK?
                    E2_Return.Status = 0;
            }
            E2Bus_stop(); // send E2 stop condition
            counter++;
        }
        return E2_Return;
    }
    /*-------------------------------------------------------------------------*/
    void E2Bus_start(void) // send Start condition to E2 Interface
    {
        set_SDA();
        set_SCL();
        delay(DELAY_FAKTOR);
        clear_SDA();
        delay(DELAY_FAKTOR);
        clear_SCL();
    }
    /*-------------------------------------------------------------------------*/
    void E2Bus_stop(void) // send Stop condition to E2 Interface
    {
        clear_SCL();
        delay(DELAY_FAKTOR);
        clear_SDA();
        delay(DELAY_FAKTOR);
        set_SCL();
        delay(DELAY_FAKTOR);
        set_SDA();
        delay(DELAY_FAKTOR);
    }
    
    /*-------------------------------------------------------------------------*/
    void E2Bus_send(unsigned int value) // send Byte to E2 Interface
    {
        unsigned int i;
        unsigned int maske = 0x80;
        for (i = 8; i > 0; i--) {
            clear_SCL();
            delay(DELAY_FAKTOR);
            if ((value & maske) != 0) {
                set_SDA();
            } else {
                clear_SDA();
            }
            delay(DELAY_FAKTOR);
            set_SCL();
            maske >>= 1;
            delay(DELAY_FAKTOR);
            clear_SCL();
        }
        set_SDA();
    }
    
    /*-------------------------------------------------------------------------*/
    unsigned int E2Bus_read(void) // read Byte from E2 Interface
    {
        unsigned int data_in = 0x00;
        unsigned int maske = 0x80;
        output_float(E2_SDA);
        for (maske = 0x01; maske<0x80; maske<<=1) 
        {
            clear_SCL();
            delay(DELAY_FAKTOR);
            set_SCL();
            delay(DELAY_FAKTOR);
            if(read_SDA()) 
            {
                data_in |= maske;
            }
            delay(DELAY_FAKTOR);
            clear_SCL();
        }
        return data_in;
    }
    
    /*-------------------------------------------------------------------------*/
    int check_ack(void) // check for acknowledge
    {
        int1 input;
        delay(DELAY_FAKTOR);
        set_SCL();
        delay(DELAY_FAKTOR);
        input = read_SDA();
        delay(DELAY_FAKTOR);
        if (input == 1)
            return NAK;
        else
            return ACK;
    }
    
    /*-------------------------------------------------------------------------*/
    void send_ack(void) // send acknowledge
    {
        clear_SCL();
        delay(DELAY_FAKTOR);
        clear_SDA();
        delay(DELAY_FAKTOR);
        set_SCL();
        delay(DELAY_FAKTOR);
        clear_SCL();
        set_SDA();
    }
    
    /*-------------------------------------------------------------------------*/
    void send_nak(void) // send NOT-acknowledge
    {
        clear_SCL();
        delay(DELAY_FAKTOR);
        set_SDA();
        delay(DELAY_FAKTOR);
        set_SCL();
        delay(DELAY_FAKTOR);
        clear_SCL();
        set_SDA();
    }
    
    /*-------------------------------------------------------------------------*/
    void delay(unsigned int value) // delay- routine
    {
        delay_ms(value);
    }
    /*-------------------------------------------------------------------------*/
    // adapt this code for your target processor !!!
    
    void set_SDA() {
        output_high(E2_SDA);
    } // set port-pin (SDA)
    
    void clear_SDA() {
        output_low(E2_SDA);
    } // clear port-pin (SDA)
    
    int read_SDA(void) 
    {
        int return_SDA;
        return_SDA=input(E2_SDA);
        return return_SDA;
    } // read SDA-pin status
    
    void set_SCL(void) {
        output_high(E2_SCL);
    } // set port-pin (SCL)
    
    void clear_SCL(void) {
        output_low(E2_SCL);
    } // clear port-pin (SCL)



    Voici mon code test :

    Main :

    Code:
    #include <18F26J50.h>
    
    #FUSES NOWDT
    #FUSES NODEBUG
    #FUSES NOXINST
    #FUSES NOPROTECT
    #FUSES NOFCMEN
    #FUSES NOIESO
    #FUSES NOCPUDIV
    #FUSES PLL2
    #FUSES INTRC_PLL
    #use delay(clock=48000000)
    
    #include <E2_driver.c>
    
    void main() 
    {
        char text;
        unsigned int taux_co2;
    
        while(1)
        { 
             taux_co2=read_co2(); // Lecture capteur
    
             sprintf(text,"%u",taux_co2); // Assignement de la valeur pour l'affichage
             glcd_text57(10,20,text,3,ON); // Envoie au LCD
             delay_ms(1000); // Delay 
        }
    }
    Driver E2:

    Code:
    #define E2_SDA   PIN_B3
    #define E2_SCL   PIN_B2
    
    #use i2c(MASTER, FAST=500, SDA=E2_SDA, SCL=E2_SCL, STREAM=E2)
    
    // Fonction de lecture du taux de CO2
    unsigned int read_co2()
    {
        unsigned int co2;
        int LB,HB;
        int checksum;
        int1 status=1;
        
        i2c_start(E2); 
        status=i2c_write(E2,0xC1);//Envoie control byte pour lecture 4 bits de poids faible + récupération acquittement
    
        // Test acquittement (validé si status=0)
        if(!status) 
        {
            LB=i2c_read(E2);  // Lecture bits de poids faible du taux de CO2
            checksum=i2c_read(E2,0);  // Lecture checksum sans renvoie d'acquittement pour libérer la ligne
        }
        i2c_stop(E2); 
        
        i2c_start(E2);
        status=i2c_write(E2,0xD1);// Envoie control byte pour lecture 4 bits de poids fort + récupération acquittement
    
        // Test acquittement (validé si status=0)
        if(!status)
        {
            HB=i2c_read(E2); // Lecture bits de poids fort du taux de CO2
            checksum=i2c_read(E2,0);  // Lecture checksum sans renvoie d'acquittement pour libérer la ligne
        }
        i2c_stop(E2);
        
        HB<<4;  // Replacer les bits de poids fort 
        
        co2=LB+HB;   // Assemblé les ensemble de bits 
        
        
        return co2;  // Renvoyer la valeur mesurée
    }
    Le problème dans ce code est que je ne reçois pas d'acquittement de la part du capteur, que certaines fois le PIC envoie les commande, parfois n'envoie que l'instruction i2c_start(); et je ne penses pas avoir tout compris le principe de cet interface E2, malgré toute mes recherche, j'ai sûrement loupé quelque chose d'essentiel.

    Dans mes recherche, j'ai lus toutes les datasheet du site, chercher sur des forum mais rien ne m'aide. (inutile donc de m'envoyé sur un lien www.epluse.com )

    Est-ce que quelqu'un pourrait m'aider ?

    Je cherche juste à mesurer le taux de CO2, l'enregistrer dans l'EEPROM ainsi que l'heure de la mesure et afficher les tout sur un graphique CO2/Date&Heure à l'aide de mon LCD graphique.

    Je vous remercie d'avance.

    ELT4
    Laboratoire d'électronique
    CEJEF Division Technique

    -----
    Dernière modification par ELT4 ; 15/03/2016 à 13h31.

  2. #2
    carcan

    Re : Problème capteur CO2 (Interface E2)

    Hello !

    ton sujet m'intéresse ... j'ai déjà été tenté plusieurs fois par ces capteurs, mais je n'en ai encore jamais acheté.

    Avant d'aborder les problèmes soft, es-tu sûr de ton hardware ?

    Tu as-fait comment pour ta conversion 5V vers 3.3V ?
    Pour le SCK, c'est facile, mais pour le SDA c'est un peu plus tiré par les cheveux car c'est du bidirectionnel.

    Tu as contrôlé à l'oscillo que tout était "beau" ?

    Je connais pas mal le compilateur CCS.

    Tu as commandé où ces capteurs ?
    Limite, si ils ne sont pas trop chers, j'en commande un aussi et on développe le code ensemble ; tu peux me laisser un mp avec ton mail et on en discute par mail.

    A+
    Laurent

  3. #3
    ELT4

    Re : Problème capteur CO2 (Interface E2)

    Salut carcan,

    Merci beaucoup pour ta réponse.

    Je te communique tout ça en message privé.

    Igor

Discussions similaires

  1. [C++] Problème d'interface (JAVA)
    Par Aenonis dans le forum Programmation et langages, Algorithmique
    Réponses: 9
    Dernier message: 02/01/2013, 21h22
  2. passer d'une interface serie a une interface parallele ?
    Par cyber37 dans le forum Électronique
    Réponses: 8
    Dernier message: 15/04/2010, 22h01
  3. Réponses: 3
    Dernier message: 30/05/2008, 10h48
  4. Réalisation interface capteur / pc
    Par invite88eac1bc dans le forum Électronique
    Réponses: 1
    Dernier message: 13/05/2008, 13h36
  5. problème interface MATLAB
    Par invite7b1518cc dans le forum Électronique
    Réponses: 0
    Dernier message: 23/09/2007, 15h24
Découvrez nos comparatifs produits sur l'informatique et les technologies.