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.

Station en fonctionnement


Version avec hygromètre (Module capteur humidite SY-HS-230 lu par un pcf8591)

Partie interface DS1621, PCF8674
Partie compteur, PCF8591 et sonde


Vu du montage sur plaquette


Exemple de relevés obtenu

Température mesuré par un ds1621, Luminosité mesuré par un capteur TSL260 lu par un pcf8591 et Pluviométrie lu par un compteur CD4040 lu par un pc8574.

Température mesurée
Pluviomètrie mesurée


Ensoleillement mesuré


Log. du programme ci-dessous:

03/06/04 03:12:44 - Lecture temp   (DS1621):        9.81 [9.8°]
03/06/04 03:12:44 - Lecture pluvio (PCF8574 P0-P5): 1 [1.0mm]
03/06/04 03:12:44 - Lecture hygro  (PCF8591 can0):  190 [78.2%]
03/06/04 03:12:44 - Lecture lux    (PCF8591 can1):  2 [2.0l]
03/06/04 03:12:44 - Lecture alim   (PCF8591 can2):  142 [5.3V]
03/06/04 03:12:44 - RRD: 9.8 1.0 78.2 2.0 5.3


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