Mon Arduino sait lire l’heure (DS1307)


DSCF1256 Arrivage d’Asie (Futurlec, une adresse à connaître !). Je reviendrai sur mes autres achats, mais ce qui m’a occupée aujourd’hui c’est une petite horloge “real time” basée sur la puce DS1307.

L’idée est que mon Arduino conserve la date et l’heure en permanence, histoire que les statistiques soient correctes.

DSCF1257

Voici la “bête” et sa référence chez  futurlec. J’ai dû me battre un peu avec les librairies DS1307 pour l’Arduino (il y a des modifications constantes), et surtout j’ai dû mettre un condensateur 10nf sur le circuit pour lisser le courant.

DSCF1262

Après quelques heures de tests et de programmation, mon Arduino sait lire (et garder !) l’heure, et encore mieux, l’afficher…

DSCF1259

Le résultat sur le port sériel (sera utilisé plus tard pour faire des statistiques sur PC), les données sont envoyées toutes les 10 secondes sur le port sériel.

DSCF1260

Le code actuel (je n’ai pas la prétention d’être une grande codeuse, alors à prendre “tel quel” ! Je commente beaucoup car j’ai peu de mémoire, alors c’est pour référence ultérieure. A noter que les pin 20 et 21 sont les ports one-wire sur l’Arduino Mega, ce sont les PIN 4 et 5 sur le modèle standard.

//**************** AquaControleur Test code ****************

//**************** Libraries ****************
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <Debounce.h>
#include <math.h>
#include <WProgram.h> //for the clock
#include <Wire.h> //for the clock
#include <DS1307.h> //for the clock

//**************** Defines PIN ****************
#define Ventilator 22
// Ventilator is put on Pin 22 – no PWM so far
// Temperature on analog 0 (no need to declare)
// SDA 20 //IC22 ports clock (no need to declare)
// SDC 21 //IC21 ports clock (no need to declare)

//Insert template for streaming
/*This allows you to write succinct code like
Serial << « My name is  » << name <<  » and I am  » << age <<  » years old. »;
or
Serial << « GPS unit # » << gpsno <<  » reports lat/long of  » << lat << « / » << long;*/
template<class T> inline Print &operator <<(Print &obj, T arg) {
obj.print(arg);
return obj;
}

//**************** LiquidCrystal display ****************
//rs on pin 12
//rw on pin 11
//enable on pin 10 d4, d5, d6, d7 on pins 5, 4, 3, 2 */
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

//**************** Other Variables ****************
//Temp Average calcs
const int NumberValuesAVG = 100; // Defines how many values the array will keep for the temp averages
double ReadingsAVG[NumberValuesAVG]; //array that contains the values
int index = 0;
double total = 0;
double average = 0;

//Temp values
#define ThermistorPIN 0   // Analog Pin 0 contains thermistor reading
double temp; //temperature var
double currentTemp = 0; //temporary Temp Variable
double HighLow[] = {
0,99,1};// HighLow[0]=High, HighLow[1]=low, HighLow[2]=AVG
double ventLimit[]  = {
26.0, 25.5}
; //first is the threshold to start vent, [0], second to stop vent [1]

//Date and Time Values
int rtc[7]; //real time clock values

//SerialPrint interval (set when we print to the serial port)
long LGpreviousMillis = 0;
long SHpreviousMillis = 0;

// Code Running intervals
long LGinterval = 10000; //interval at which the serial data is updated, here 10 secs
long SHinterval = 1000; //actions to run more often (every sec)

//**************** Thermistor Functions ****************
//Schematic:
// [Ground] —- [10k-Resister] ——-|——- [Thermistor] —- [+5v]
//                                     |
//                                Analog Pin 0
// using a 4.7K thermistor

// Inputs ADC Value from Thermistor and outputs Temperature in Celsius
//  requires: include <math.h>
// Utilizes the Steinhart-Hart Thermistor Equation:
//    Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3}
//    where A =0.0012819121, B = 0.00023789205 and C = 0.00000010217758
// Values for a,b,c taken from spec sheet here (p. 33 ) :: http://www.epcos.com/inf/50/db/ntc_06/LeadedDisks__B57164__K164.pdf then
// calculated from : http://www.capgo.com/Resources/Temperature/Thermistor/ThermistorCalc.html
//Thermistor code from http://www.arduino.cc/playground/ComponentLib/Thermistor2 (short code)

double Thermister(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) – 10000));
Temp = 1 / (0.0012819121 + (0.00023789205 * Temp) + (0.00000010217758 * Temp * Temp * Temp));
Temp = Temp – 273.15;            // Convert Kelvin to Celsius
//Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
return Temp;
}

//RTC Functions

void printDec2(byte decVal)
{
if (decVal < 10)
Serial.print(« 0 »);
Serial.print(decVal, DEC);
}

void printLCDDec2(byte decVal)
{
if (decVal < 10)
lcd.print(« 0 »);
lcd.print(decVal, DEC);
}

void printDayName(byte d)
{
switch (d) {
case 1:
Serial.print(« MON »);
break;
case 2:
Serial.print(« TUE »);
break;
case 3:
Serial.print(« WED »);
break;
case 4:
Serial.print(« THU »);
break;
case 5:
Serial.print(« FRI »);
break;
case 6:
Serial.print(« SAT »);
break;
case 7:
Serial.print(« SUN »);
break;
default:
Serial.print(« ??? »);
}
}

// **************** SETUP ****************
void setup()
{
//Define the time — Uncomment to reset date/time (one-time operation)
/*RTC.stop();
RTC.set(DS1307_SEC,1);
RTC.set(DS1307_MIN,38);
RTC.set(DS1307_HR,17);
RTC.set(DS1307_DOW,7);
RTC.set(DS1307_DATE,19);
RTC.set(DS1307_MTH,07);
RTC.set(DS1307_YR,9);
RTC.start();*/

// start serial port at 9600 bps:
Serial.begin(9600);

//Clear Screen
lcd.clear();
lcd.home();
lcd << « Starting Up… » ;

//Init variables
pinMode (Ventilator, OUTPUT); //defines the ventilator is an output
HighLow[2] = Thermister(analogRead(0));

//Init RTC variables
for(int i=0; i<56; i++)
{
RTC.set_sram_byte(65,i);
}

}

// **************** LOOP ****************
void loop()
{

//**** TIME ****
RTC.get(rtc,true); // set the RTC

//Update time variables
byte sec = rtc[0];
byte min = rtc[1];
byte hour = rtc[2];
byte dow = rtc[3];
byte date = rtc[4];
byte month = rtc[5];
int year = rtc[6];

//**** TEMPERATURE ****
//Read Thermistor value
currentTemp = Thermister(analogRead(0));
//**** Actions do to in a short interval (here every 1 secs)

if (millis() – SHpreviousMillis > SHinterval) {
SHpreviousMillis = millis();

//print Temp on LCD
lcd.home();
lcd << « T: » << currentTemp <<  » « ;
printLCDDec2(hour);
lcd.print (« : »);
printLCDDec2(min);
lcd.print (« : »);
printLCDDec2(sec);
//lcd << « T: » << currentTemp <<  » A: » << HighLow[2]; //temp & average
lcd.setCursor (0,1);
lcd << « L: » << HighLow[1] <<  » H: » << HighLow[0];
if (currentTemp < HighLow[1] )
{
HighLow[1] = currentTemp;
}
else if (currentTemp > HighLow[0]){

HighLow[0] = currentTemp;

}

}

//**** Actions with do every X seconds (defined by the Interval value  **** (here every 10 secs)
if (millis() – LGpreviousMillis > LGinterval) {
// save the last time serialPrint was done
LGpreviousMillis = millis();

//Calculate the AVG to avoid a calc that is too quick
//Average calculation
total= total – ReadingsAVG[index];
ReadingsAVG[index]= currentTemp;
total = total + ReadingsAVG[index];
index = index + 1;
//Calculates the AVG when the number of readings is reached
if (index >=NumberValuesAVG){
index = 0;
HighLow[2]=total/NumberValuesAVG;
}

//Print values on Serial for debugging & future logging on PC
// Prints the date
printDec2(hour);
Serial.print (« : »);
printDec2(min);
Serial.print (« : »);
printDec2(sec);
Serial.print ( » « );
printDayName(dow);
Serial.print ( » « );
printDec2(date);
Serial.print (« / »);
printDec2(month);
Serial.print (« / »);
Serial.print(year);

Serial <<  » |L  » << HighLow[1] <<  » |H  » << HighLow[0] << » |C  » << currentTemp <<  » |A  » << HighLow[2];
Serial.println( » « );

if (currentTemp >= ventLimit[0] && digitalRead(Ventilator) == LOW){ //put Ventilator on if temp > 26 and if vent is off
digitalWrite(Ventilator, HIGH);
lcd.home();
lcd.clear();
lcd << « T: » << currentTemp << « >=LM: » << ventLimit[0] ;
lcd.setCursor (0,1);
lcd << « Vent Starting »;
//printdate
printDec2(hour);
Serial.print (« : »);
printDec2(min);
Serial.print (« : »);
printDec2(sec);
Serial.print ( » « );
printDayName(dow);
Serial.print ( » « );
printDec2(date);
Serial.print (« / »);
printDec2(month);
Serial.print (« / »);
Serial.print(year);
Serial <<  » Temp :  » << currentTemp <<  » Ventilator Starting »;
Serial.println( » « );
}
else if (currentTemp <= ventLimit[1] && digitalRead(Ventilator) == HIGH) { // puts ventilator down if temp lower than 25.5 and if the vent is on
digitalWrite (Ventilator, LOW);
lcd.home();
lcd.clear();
lcd << « T: » << currentTemp << « <=LM: » << ventLimit[1] ;
lcd.setCursor (0,1);
lcd << « Vent Stopping »;
//printdate
printDec2(hour);
Serial.print (« : »);
printDec2(min);
Serial.print (« : »);
printDec2(sec);
Serial.print ( » « );
printDayName(dow);
Serial.print ( » « );
printDec2(date);
Serial.print (« / »);
printDec2(month);
Serial.print (« / »);
Serial.print(year);
Serial << « Temp :  » << currentTemp <<  » Ventilator Stopping »;
Serial.println( » « );

}

}

}

7 réflexions sur “Mon Arduino sait lire l’heure (DS1307)

  1. Bravo! Je suis a peu pres au meme stade, j’ai bricole un petit circuit avec un DS1307, je sais lire des temperatures, et je sais controller un ecran (j’utilise le s65-shield de watterott). Bon courage!

  2. Pingback: Temperature Measurement | Engineer Sphere

  3. Bonjour,

    Je suis impressionné par votre montage, et je me suis lancé, j’ai commander un kit complet avec le Mega et l’afficheur, j’aimerais rajouter l’horloge et pourquoi pas un Ethernet.

    Je vous remercie pour votre code, je vais analyser tout sa lorsque j’aurais reçu le matériel.
    Avez vous avancé depuis (rajouter des fonctions).

    Vu que je n’ai encore le matériel, je ne peut pas encore vérifié le fonctionnement mais je comprend pas encore les modifications que vous avez effectuées sur la librairie DS1307 et ou se situe le condensateur dans le montage.

    Merci

  4. Pour ce qui est de la librairie, j’ai peiné à trouver la bonne en réalité. Il y a plusieurs versions et toutes ne marchaient pas. Mais à mon souvenir (ça date quasiment d’un an à présent !), je n’ai pas modifié la librairie elle-même. Je suis sûre qu’on trouve aujourd’hui des librairies à jour pour cette horloge.

    Le condensateur se trouve simplement dans le circuit, à l’entrée du courant positif. Il n’est pas forcément indispensable, dans mon montage l’horloge ne fonctionnait pas bien sans lui.

  5. Bonjour,

    Merci pour cette note très intéressante. Je me lance aussi dans l’électronique pour faire un thermostat d’ambiance. Pour l’instant je n’ai mis que le capteur de temperature et le relais, mais j’envisage de mettre un écran LCD pour améliorer l’IHM de l’ensemble.
    Avez vous fait d’autres progrès avec Arduino ?

    Fabien

  6. Projet un peu en berne pour le moment (par manque de temps !) donc pas de gros progrès. Mais il n’est pas exclu que je m’y remette😉

  7. Bravo pour le topic! Merci pour le partage. Par contre avec un condensateur c’est une tension qu’on lisse et non un courant sinon c’est une inductance.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s