Les sondes sont des DS18B20.
Je me suis donc équipé du arduino uno, d'un shield mémoire et d'un shield deuligne.
Le montage des trois cartes:
Le test du système, les 4 sondes au même endroit et un contrôle par un thermomètre indépendant:
Sur cette dernière photo la mesure n'est pas stabilisée et on arrive au final avec un écart entre +0 et +0.5 °C.
L'affichage sur le Deuligne comprend sur la 1ère ligne la date puis 2 sondes et sur la 2ème ligne l'heure et les deux autres sondes.
L'écran peut être allumé ou éteint par appui sur le bouton du Deuligne.
Les données sont enregistrées sur une carte SD par le shield mémoire.
Je viens donc de me mettre à la programmation pour Arduino et auparavant je n'avais jamais codé en C. Il y a certainement des améliorations à y apporter, je compte sur vous. L'utilisation de la mémoire vive est limite et m'a obligé à revoir à la baisse mes ambitions, je souhaitais pouvoir régler l'heure par le joystick du Deuligne et d'autres petits trucs comme ça... Si vous voyez des pistes pour baisser l'utilisation de mémoire n'hésitez pas à m'en faire part.
Voici le code:
- Code: Tout sélectionner
#include <Wire.h>
#include <RTClib.h>
#include <SD.h>
#include <Deuligne.h>
#include <OneWire.h>
#include <avr/pgmspace.h>
#define NBRE_CAPTEUR 4 // nombre de capteur sur l'arduino
#define DELAI 60 //nombre de secondes entre deux mesures
#define DS1307_I2C_ADDRESS 0x68 // deuligne afficheur LCD
// *********** declararation des variables gestion des capteurs de temperature *******************
typedef struct Temperature Temperature;
struct Temperature
{
float valeur; // temperature en Celsius, 1 chiffre apres la virgule
byte addr[8]; // identifiant capteur
byte pin; // numero de pin a utiliser
char mnemo[5]; // mnemonique de la variable
};
Temperature temperature[NBRE_CAPTEUR]; //creation des instances
const byte PIN_CAPTEUR = 8; //Pin sur laquelle sont branchés les capteurs
// *********** fin declararation des variables gestion des capteurs de temperature *******************
// autres variables
unsigned long temps, temps2;
byte i=0;
RTC_DS1307 RTC;
DateTime moment; //Création d'un objet contenant les données temporelles
File fichier;
// variables pour le Deuligne
Deuligne lcd;
byte a=0;
boolean b=0;
String second, minute, hour, day, month, year;
//pour le SD
const byte chipSelect = 10;
byte carte;
void setup(){
Serial.begin(57600); // initialisation de la liaison serie
// *********** initialisation des variables gestion des capteurs de temperature *******************
temperature[0].addr[0]= 0x28; // identifiant capteur
temperature[0].addr[1]= 0xa3;
temperature[0].addr[2]= 0x8e;
temperature[0].addr[3]= 0xbf;
temperature[0].addr[4]= 0x3;
temperature[0].addr[5]= 0x0;
temperature[0].addr[6]= 0x0;
temperature[0].addr[7]= 0x9d;
temperature[0].pin=PIN_CAPTEUR;
temperature[0].valeur=0; // temperature en °C, 1 chiffre apres la virgule
strcpy(temperature[0].mnemo,"Int_E"); // intérieur entrant
temperature[1].addr[0]= 0x28; // identifiant capteur
temperature[1].addr[1]= 0x36;
temperature[1].addr[2]= 0xac;
temperature[1].addr[3]= 0xbf;
temperature[1].addr[4]= 0x03;
temperature[1].addr[5]= 0x0;
temperature[1].addr[6]= 0x0;
temperature[1].addr[7]= 0xbc;
temperature[1].pin=PIN_CAPTEUR;
temperature[1].valeur=0; // temperature en °C, 1 chiffre apres la virgule
strcpy(temperature[1].mnemo,"Int_S"); // Intérieur sortant
temperature[2].addr[0]= 0x28; // identifiant capteur
temperature[2].addr[1]= 0x5c;
temperature[2].addr[2]= 0x86;
temperature[2].addr[3]= 0xbf;
temperature[2].addr[4]= 0x3;
temperature[2].addr[5]= 0x0;
temperature[2].addr[6]= 0x0;
temperature[2].addr[7]= 0xf5;
temperature[2].pin=PIN_CAPTEUR;
temperature[2].valeur=0; // temperature en °C, 1 chiffre apres la virgule
strcpy(temperature[2].mnemo,"Ext_E"); // extérieur entrant
temperature[3].addr[0]= 0x28; // identifiant capteur
temperature[3].addr[1]= 0xe6;
temperature[3].addr[2]= 0xc6;
temperature[3].addr[3]= 0xbf;
temperature[3].addr[4]= 0x3;
temperature[3].addr[5]= 0x0;
temperature[3].addr[6]= 0x0;
temperature[3].addr[7]= 0xd4;
temperature[3].pin=PIN_CAPTEUR;
temperature[3].valeur=0; // temperature en °C, 1 chiffre apres la virgule
strcpy(temperature[3].mnemo,"Ext_S"); // extérieur entrant
// initialisation pour le deuligne
Wire.begin();
lcd.init();
// initialisation RTC et temps avec ordinateur si besoin
RTC.begin();
if (! RTC.isrunning())
{
RTC.adjust(DateTime(__DATE__, __TIME__));
}
// initialisation SD
carte=1;
pinMode(chipSelect, OUTPUT); // Mettre la pin en output
if (!SD.begin(chipSelect)) // Vérification de la présence de la SD card
{
lcd.backLight(1);
lcd.print("Carte fausse");
lcd.setCursor(5,1);
lcd.print("ou absente");
delay(4000);
carte=0;
lcd.backLight(0);
}
if (!SD.exists("Donnees.txt")) // Si le fichier n'existe pas
{
fichier = SD.open("Donnees.txt", FILE_WRITE); // Ouverture du fichier en mode Ecriture.
fichier.print("Date");
for (i=0 ; i<NBRE_CAPTEUR ; i++ )
{
fichier.print(";");
fichier.print(temperature[i].mnemo);
}
fichier.println();
fichier.close();
}
}
void loop(){
triDate();
temps=(moment.unixtime() + DELAI);
temps2 = moment.unixtime()+10;
gestion_temperature();
// affichage des températures sur le lcd
lcd.setCursor(6,0);
lcd.print(temperature[0].valeur,1);
lcd.print(" "); //efface le 4ème caractère éventuel si < -10
lcd.setCursor(11,0);
if (temperature[1].valeur >= -10) //efface le 4ème caractère éventuel si < -10
{
lcd.print(" ");
}
lcd.print(temperature[1].valeur,1);
lcd.setCursor(6,1);
lcd.print(temperature[2].valeur,1);
lcd.print(" "); //efface le 4ème caractère éventuel si < -10
lcd.setCursor(11,1);
if (temperature[3].valeur >= -10) //efface le 4ème caractère éventuel si < -10
{
lcd.print(" ");
}
lcd.print(temperature[3].valeur,1);
if (carte) // test si une carte SD est présente
{
enregistrement_sd();
}
/*****************************************************
* cree une boucle permettant d'intercepter un appui *
* eventuel sur le bouton pour allumer le deuligne *
*****************************************************/
while (moment.unixtime() < temps) //attente du délai
{
triDate(); //Init de l'objet temporel
lcd.setCursor(0,0);
lcd.print(day + '/' + month);
lcd.setCursor(0,1);
lcd.print(hour + 'h' + minute); //+"/"+month;
if (moment.unixtime() > (temps2)) //affichage des températures toutes les 10 secondes
{
temps2 = moment.unixtime()+10;
gestion_temperature();
// affichage des températures sur le lcd
lcd.setCursor(6,0);
lcd.print(temperature[0].valeur,1);
lcd.print(" "); //efface le 4ème caractère éventuel si < -10
lcd.setCursor(11,0);
if (temperature[1].valeur >= -10) //efface le 4ème caractère éventuel si < -10
{
lcd.print(" ");
}
lcd.print(temperature[1].valeur,1);
lcd.setCursor(6,1);
lcd.print(temperature[2].valeur,1);
lcd.print(" "); //efface le 4ème caractère éventuel si < -10
lcd.setCursor(11,1);
if (temperature[3].valeur >= -10) //efface le 4ème caractère éventuel si < -10
{
lcd.print(" ");
}
lcd.print(temperature[3].valeur,1);
}
a=lcd.get_key();
if (a==4) // someone pressed 'enter'
{
b=!b;
lcd.backLight(b); //on inverse l'allumage de l'écran
delay(500);
}
}
}
void gestion_temperature()
{
/********************************************************************************
* Cette fonction permet d'interroger tous les capteurs de temperature OneWire
* qui ont ete declare dans "temperature[i]"
********************************************************************************/
for(i=0; i<NBRE_CAPTEUR; i++)
{
temperature[i].valeur =getStuff(temperature[i].addr,temperature[i].pin);
}
}
float getStuff(byte addr[8], int pin) // indiquer le n� de pin � utiliser
{
/********************************************************************************
* Cette fonction permet d'interroger le capteur de temperature OneWire
* qui a �t� d�clar� dans "temperature[i]"
********************************************************************************/
byte j=0;
OneWire ds(pin); // creation d'un objet OneWire avec le bon n� de pin
// byte present = 0;
byte data[12];
float real_temp;
float temp_count;
float read_temp;
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power off at the end (1=parasite mode)
delay(1000); // delay de 1s si mode parasite. 100ms en mode normal
// we might do a ds.depower() here, but the reset will take care of it.
// present = ds.reset();
ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( j = 0; j < 9; j++) { // we need 9 bytes
data[j] = ds.read();
}
read_temp=((data[1]<<8) | data[0]);
real_temp=float(read_temp)*6.25;
real_temp=real_temp/100;
return real_temp;
}
void enregistrement_sd()
{
fichier = SD.open("Donnees.txt", FILE_WRITE); // Ouverture du fichier en mode Ecriture.
triDate();
fichier.print(year + "/" + month + "/" +
day + " " + hour + ":" +
minute + ":" + second);
for (i=0 ; i<NBRE_CAPTEUR ; i++ )
{
fichier.print(";");
if (i==NBRE_CAPTEUR-1)
{
fichier.println(temperature[i].valeur);
}
else
{
fichier.print(temperature[i].valeur);
}
}
fichier.close();
// Serial.println("\n[memCheck]");
Serial.println(freeRam());
}
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
void triDate()
{
moment = RTC.now();
year=moment.year();
if (moment.month()<10)
{
month = "0"+String(moment.month(),DEC);
}
else
{
month = String(moment.month(),DEC);
}
if (moment.day()<10)
{
day = "0"+String(moment.day(),DEC);
}
else
{
day = String(moment.day(),DEC);
}
if (moment.hour()<10)
{
hour = "0"+String(moment.hour(),DEC);
}
else
{
hour = String(moment.hour(),DEC);
}
if (moment.minute()<10)
{
minute = "0"+String(moment.minute(),DEC);
}
else
{
minute = String(moment.minute(),DEC);
}
if (moment.second()<10)
{
second = "0"+String(moment.second(),DEC);
}
else
{
second = String(moment.second(),DEC);
}
}