Mini station meteo i2c
De MicElectroLinGenMet.
Sommaire |
Description
Shéma partie i2c
Shéma de la mini station météo.
- La partie electronique du pluviomètre est réalisé avec un compteur électronique (4040) lu par un PCF8574 (CI i2c) par interval. La partie mécanique est reprise d'un modèle du commerce: Pluviometre filaire electronique.
- Station pilotée par une interface i2c sous Linux: yail-i2c dans un premier temps et remplacée par une interface personnelle : Interface serial-i2c.
Station en test
Photo de la station en fonctionnement, version de départ température (ds1621) + pluviomète (pcf8574) pilotée par yail-i2c.
Version avec hygromètre (Module capteur humidite SY-HS-230 lu par un pcf8591)
Exemple de relevés obtenu
Luminosité mesuré par un capteur TSL260 lu par un pcf8591
Exemple de programme C sous Linux
/*********************************************************** StationMeteo ***********************************************************/ /* This code is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ /* works with all the Yail-I2C library/drivers */ /* Station méteo I2C */ /* Gére la t° (ds1621), la pluviométrie (PCF8574 + 4040 + mécanique pluviomètre) */ /* Hygromètre (PCF8591 + Module SY-HS-230 Sélectronic), Luxmètre (PCF8591 + TLS260 */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include "getopt.h" #include <time.h> #include <locale.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <signal.h> #include <fcntl.h> #include "./libi2c.h" #define FRACTIONNAIRE /* Lower bound for variations */ #define EPSIL 20 /* this is the default address */ #define DS1621_ADR 0x9E #define PCF8574_ADR 0x40 #define PCF8591_ADR 0x98 #define LOG "/var/www/stationmeteo/stationmeteo.log" #define CONV_DELAY 500 // Déclaration pour la date. time_t td; struct tm *dc; char sdate[64]; int minutes_courantes ; char logtext[255] ; //----------------------------------------------------------------------------- void PrintLog(char logtext[]) { /* Ouverture fichier log */ FILE *stationmeteolog ; time(&td) ; //Lit date/heure système. dc = localtime(&td) ; strftime(sdate,sizeof sdate,"%d/%m/%y %H:%M:%S",dc); if ((stationmeteolog = fopen(LOG, "a")) == NULL) { fprintf(stderr, "### Erreur ouverture fichier log en ajout !") ; fprintf(stderr, "### Fin programme !") ; exit(-1); } fprintf(stationmeteolog, "%s - %s", sdate, logtext) ; fclose(stationmeteolog) ; } //----------------------------------------------------------------------------- int main(int argc, char **argv) { u_char adth, adio, adcan; u_char init_io ; //Valeur par defaut pcf8574. u_short acki2c ; int finprog ; unsigned char led = 0x80 ; unsigned char clr_compteur_pluvio = 0x40 ; unsigned char io0_5 ; unsigned char can0 ; unsigned char can1 ; unsigned char can2 ; unsigned char can3 ; unsigned char offset_hygro = 4 ; //Rajout au % hygro pour étalonnage avec frog. float temperature ; float pluvio ; float hygro ; float lux ; float alim ; int erreuri2c ; long delay; int count,slope,temp; char buf[256]; int k; char cc; /* DS1621 address */ adth=DS1621_ADR; adio=PCF8574_ADR; adcan=PCF8591_ADR; delay=CONV_DELAY*1000; init_io = 0xFF ; erreuri2c = 0 ; PrintLog("Démarrage de stationmeteo i2c -----------------------------------\n") ; if (i2c_init(0)) { //fprintf(stderr,"Erreur initialisation bus I2C !\n"); PrintLog("### Erreur initialisation bus I2C !\n") ; PrintLog("### Abandon du programme !\n") ; exit(-1); } /* DS1621 setup */ buf[0]=0xAC; buf[1]=1; if ( (acki2c = i2c_write(adth,buf,2)) != 2 ) { sprintf(logtext, "### Erreur init DS1621: ack=%d !\n", acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } /* PCF8574 setup */ buf[0]=init_io; if ( (acki2c = i2c_write(adio,buf,1)) != 1 ) { sprintf(logtext, "### Erreur init PCF8574: ack=%d !\n", acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } /* PCF8591 setup */ buf[0]=0x00; if ( (acki2c = i2c_write_read(adcan,buf,1,buf,1)) != 1 ) { sprintf(logtext, "### Erreur test PCF8591: ack=%d !\n", acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } /* start temperature conversion */ buf[0]=0xEE; i2c_write(adth,buf,1); usleep(delay); /* conversion delay */ /* Raz compteur pluvio.*/ buf[0]=init_io & ~clr_compteur_pluvio ; //clr_compteur_pluvio à 0. i2c_write(adio,buf,1); usleep(CONV_DELAY); buf[0]=init_io; i2c_write(adio,buf,1); minutes_courantes = 0 ; finprog = 0; while (! finprog) { /* stop conversion */ buf[0]=0x22; acki2c = i2c_write(adth,buf,1); /* Temperature reading (1 Celsius degree precision) */ buf[0]=0xAA; if ( (acki2c = i2c_write_read(adth,buf,1,buf,1)) == 1 ) { temp=buf[0]; /* Counter reading (fraction of degree) ) */ buf[0]=0xA8; i2c_write_read(adth,buf,1,buf,1); count=buf[0]; /* slope reading */ buf[0]=0xA9; i2c_write_read(adth,buf,1,buf,1); slope=buf[0]; k=temp; if (slope != 0) { k=temp*100-25+(100*(slope-count))/slope; } temperature=(float)k/100 ; sprintf(logtext, "Lecture temp (DS1621): %2.2f [%2.1f°]\n", temperature, temperature) ; PrintLog(logtext) ; } else { sprintf(logtext, "### Erreur ecriture/lecture DS1621 (lecture temperature): ack=%d !\n", acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } /* Teste si heure à minuit pour raz compteur pluvio. */ strftime(sdate,sizeof sdate,"%H:%M",dc); if ( strcmp(sdate, "00:00") == 0 ) //Si heure à 00:00. { /* Raz compteur pluvio.*/ buf[0]=init_io & ~clr_compteur_pluvio ; //clr_compteur_pluvio à 0. i2c_write(adio,buf,1); usleep(CONV_DELAY); buf[0]=init_io; i2c_write(adio,buf,1); } /* Lecture compteur pluvio. */ if ( (acki2c = i2c_read(adio,buf,1)) == 1 ) { io0_5 = buf[0] & 0x3F ; //Supprime bit inutilisé pour compteur. pluvio = (float)io0_5 / 2 ; //Conversion mm. sprintf(logtext, "Lecture pluvio (PCF8574 P0-P5): %d [%2.1fmm]\n", io0_5,pluvio) ; PrintLog(logtext) ; } else { sprintf(logtext, "### Erreur lecture PCF8574 (lecture compteur pluvio.): ack=%d !\n" , acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } /* Lecture hygro (can0). */ buf[0]=0x00; i2c_write_read(adcan,buf,1,buf,1) ; //Acquisition canal0. buf[0]=0x00; if ( (acki2c = i2c_write_read(adcan,buf,1,buf,1)) == 1 ) //Lecture dernière acquisition. { can0 = buf[0] ; hygro = ((float)can0 / 256) * 100 + offset_hygro ; //Conversion en %. sprintf(logtext, "Lecture hygro (PCF8591 can0): %d [%2.1f%%]\n", can0, hygro) ; PrintLog(logtext) ; } else { sprintf(logtext, "### Erreur lecture PCF8591 (can0, hygro): ack=%d !\n" , acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } // Lecture lux (can1). buf[0]=0x01; //Acquisition canal1. i2c_write_read(adcan,buf,1,buf,1) ; buf[0]=0x01; if ( (acki2c = i2c_write_read(adcan,buf,1,buf,1)) == 1 ) //Lecture dernière acquisition. { can1 = buf[0] ; lux = ((float)can1 / 100) * 100 ; //Calcul abitraire. sprintf(logtext, "Lecture lux (PCF8591 can1): %d [%2.1fl]\n", can1, lux) ; PrintLog(logtext) ; } else { sprintf(logtext, "### Erreur lecture PCF8591 (can1): ack=%d !\n" , acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } // Lecture alim 5V (can2). buf[0]=0x02; //Acquisition canal1. i2c_write_read(adcan,buf,1,buf,1) ; buf[0]=0x02; if ( (acki2c = i2c_write_read(adcan,buf,1,buf,1)) == 1 ) //Lecture dernière acquisition. { can2 = buf[0] ; alim = (float)can2 * 0.037 ; //Pont diviseur (100k/100k+270k) => 1.43 (143) x 0.037 = 5.30V sprintf(logtext, "Lecture alim (PCF8591 can2): %d [%2.1fV]\n", can2, alim) ; PrintLog(logtext) ; } else { sprintf(logtext, "### Erreur lecture PCF8591 (can2): ack=%d !\n" , acki2c) ; PrintLog(logtext) ; erreuri2c++ ; } /* Test erreur i2c.*/ if ( ! erreuri2c ) { /* Log données pour RRD. */ sprintf(logtext, "RRD: %2.1f %2.1f %2.1f %2.1f %2.1f\n", temperature, pluvio, hygro, lux, alim) ; PrintLog(logtext) ; ; } else { /* Log données pour RRD. */ sprintf(logtext, "RRD: N/A N/A N/A N/A\n") ; PrintLog(logtext) ; } /* Clignote LED acquisition. */ buf[0]=init_io & ~led ; //Allume led acquisition. i2c_write(adio,buf,1); usleep(delay); buf[0]=init_io; //Eteint led acquisition. i2c_write(adio,buf,1); /* Relance conversion de la temperature. */ buf[0]=0xEE; i2c_write(adth,buf,1); /* Quitte si trop d'erreurs I2C. */ if (erreuri2c > 15) { sprintf(logtext, "### Erreur I2C trop importantes: erreuri2c=%d !\n", erreuri2c) ; PrintLog(logtext) ; PrintLog("##### Abandon programme #####!\n") ; i2c_close(); exit(-1); } sleep(60); } i2c_close(); PrintLog("Fin du programme !") ; exit(0); }
2004
