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.
J'ai lus que le bus E2 tourne entre 500 et 5000Hz alors j'ai essayé ceci :Code:#use i2c(MASTER, SDA=PIN_B3, SCL=PIN_B2, STREAM=E2)
J'ai également essayé leur driver qui semble recréer de l'I2C manuellement.Code:#use i2c(MASTER, FAST=500, SDA=PIN_B3, SCL=PIN_B2, STREAM=E2)
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 :
Driver E2: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 } }
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.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 }
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
-----