DS3231 - comment ça marche ? déclencher une action à une heure précise

Bonjour à tous,

J'aurais besoin de quelques infos concernant le module DS 3231. Je m'explique, je suis débutant et j'ai un niveau de survie me permettant de faire des programmes courts et pas trop complexes : je maitrise les digitalwrite, digitalRead, if, and, else, delay mais ça s'arrête là.

J'ai fouillé le net, je trouve une multitude de choses sans trop les comprendre.

J'aimerais déjà pour commencer, pouvoir allumer une led à une heure précise, et la laisser allumer un certain temps avant de l'éteindre.

J'ai commencé un sketch, j'ai inclus la bibliothèque relative au DS 3231, mais après c'est la page blanche. Je peux bien copier des codes trouvés sur le net permettant d'acquérir et lire l'heure sur l'arduino mais j'ai aucune idée de ce que je dois faire pour remplir ma condition : allumer une led si l'heure est égale à 18h00 par exemple.

Est-ce que qqun se sent de m'expliquer, si possible en mettant des // pour m'aider à comprendre à quoi correspondent les instructions / fonctions ? J'ai trouvé tout un tas de fonctions sur le site où j'ai téléchargé la bibliothèques (examples) mais j'avoue je nage, je vais pas savoir les paramétrer.

merci d'avance pour votre aide !

[code]
#include <Wire.h>
#include <ds3231.h>

struct ts t; //déclaration variable t 

void setup() {
  Serial.begin(9600);
  Wire.begin();
  DS3231_init(DS3231_INTCN);
  
  t.hour=12; // données pour mettre à l'heure l'horloge
  t.min=22;
  t.sec=0;
  t.mday=18;
  t.mon=12;
  t.year=2016;
  
  DS3231_set(t); // mise à l'heure de l'horloge
}

void loop() {
  // put your main code here, to run repeatedly:
  DS3231_get(&t);
  Serial.print("date : ");
  Serial.print(t.mday);
  Serial.print("/");
  Serial.print(t.mon);
  Serial.print("/");
  Serial.print(t.year);
  Serial.print("\t Heure : ");
  Serial.print(t.hour);
  Serial.print(":");
  Serial.print(t.min);
  Serial.print(".");
  Serial.println(t.sec);

  delay(500);
}
[/code]

Utilisez la bibliothèque RTClib de adafruit et la classe DateTime et TimeSpan qui sont bien pratiques pour des opérations sur les heures

Plus d’info ici

Bonjour

Une solution simple est de calculer le temps en secondes écoulées depuis minuit :

uint32_t secondesDepuisMinuit( uint8_t h, uint8_t m, uint8_t s )
{
	return ( h * 3600UL ) + ( m * 60UL ) + s;
}

Ensuite il suffit de faire quelque chose comme ça

static bool etatLed = false;
uint32_t secondes = secondesDepuisMinuit( t.hour, t.min, t.sec );

if ( etatLed == false && secondes >= secondesDepuisMinuit( 18, 0, 0 ) && secondes < secondesDepuisMinuit( 19, 0, 0 ) )
{
  allumerLed();
  etatLed = true;
}
else if ( etatLed == true && secondes >= secondesDepuisMinuit( 19, 0, 0 ) )
{
  eteindreLed();
  etatLed = false;
}

Dans cet exemple la LED sera allumée de 18h à 19h..

Déjà nous donner un lien vers la librairie que tu utilises. Il y a souvent plein d'informations dans les fichiers .h .
Le DS3231 a deux registres d'alarme, plus des registres de configuration pour la gestions desdites alarmes. Une librairie spécifique au DS3231 devrait avoir des méthodes pour gérer ces alarmes.

Attention aux types par défaut (int) et aux débordements !!!
faire comme cela sera plus sûr
return ( 3600ul * h ) + ( 60ul * m) + s;

1 Like

Ah oui tu as raison, je suis habitué à l'ESP32 qui n'a pas ce problème de débordement (dans ce cas là) :wink:

oui, sur ESP32 les int sont sur 32 bits donc on n'a pas le problème !

Salut !

Merci pour vos réponses !

Alors je vous donne le lien vers la bibliothèque utilisée : GitHub - rodan/ds3231: arduino library for DS3231 RTC

Je vais tenter la solution de Guix et JML, j'espère réussir à faire ça correctement... Je vous tiens informés !

Dans le répertoire d'exemples installés avec le librairie il y a un programme rtc_ds3231_alarm ça vaudrait peut-être le coup d'y jeter un œil.

Alors j'ai essayé de m'approprier le code de Guix, agrémenté par l'amélioration de JML, j'ai fait un petit montage, mais la LED ne s'allume pas...

Qu'est ce que j'ai mal fait ?

Merci !

[code]
#include <Wire.h>
#include <ds3231.h>

struct ts t; //déclaration variable t 

uint32_t secondesDepuisMinuit( uint8_t h, uint8_t m, uint8_t s )
{return ( 3600ul * h ) + ( 60ul * m) + s;}



static bool etatLed = false;
uint32_t secondes = secondesDepuisMinuit( t.hour, t.min, t.sec );

const int LED = 2;


void setup() {
  Serial.begin(9600);
  Wire.begin();

  pinMode (LED, OUTPUT);

 
  
  t.hour=14; // données pour mettre à l'heure l'horloge
  t.min=49;
  t.sec=0;
  t.mday=17;
  t.mon=8;
  t.year=2021;
  
  DS3231_set(t); // mise à l'heure de l'horloge

  
}

void loop() {
  // put your main code here, to run repeatedly:
  DS3231_get(&t);
  Serial.print("date : ");
  Serial.print(t.mday);
  Serial.print("/");
  Serial.print(t.mon);
  Serial.print("/");
  Serial.print(t.year);
  Serial.print("\t Heure : ");
  Serial.print(t.hour);
  Serial.print(":");
  Serial.print(t.min);
  Serial.print(".");
  Serial.println(t.sec);

  delay(500);


if ( secondes >= secondesDepuisMinuit( 14, 50, 0 ) )
{
  digitalWrite(LED, HIGH);
  delay (60000);
  digitalWrite(LED, LOW);
}


}
[/code]

Eureka !

Je viens de tenter un truc sans trop y croire, mais ça a l'air de fonctionner.

Alors ça n'est peut être pas très propre comme code, mais ça a fonctionné chez moi.

Autre question générale concernant l'arduino, lorsque l'on met un delay, gèle t-il les autres fonctions / conditions pendant qu'il exécute le delay ou alors est-ce qu'il continue en arrière plan de faire tourner les autres conditions de la loop ?

[code]
#include <Wire.h>
#include <ds3231.h>

struct ts t; //déclaration variable t 

uint32_t secondesDepuisMinuit( uint8_t h, uint8_t m, uint8_t s )
{return ( 3600ul * h ) + ( 60ul * m) + s;}



static bool etatLed = false;
uint32_t secondes = secondesDepuisMinuit( t.hour, t.min, t.sec );

const int LED = 2;


void setup() {
  Serial.begin(9600);
  Wire.begin();

  pinMode (LED, OUTPUT);

 
  
  t.hour=14; // données pour mettre à l'heure l'horloge
  t.min=59;
  t.sec=45;
  t.mday=17;
  t.mon=8;
  t.year=2021;
  
  DS3231_set(t); // mise à l'heure de l'horloge

  
}

void loop() {
  // put your main code here, to run repeatedly:
  DS3231_get(&t);
  Serial.print("date : ");
  Serial.print(t.mday);
  Serial.print("/");
  Serial.print(t.mon);
  Serial.print("/");
  Serial.print(t.year);
  Serial.print("\t Heure : ");
  Serial.print(t.hour);
  Serial.print(":");
  Serial.print(t.min);
  Serial.print(".");
  Serial.println(t.sec);

  delay(500);


if (( t.hour == 15 ) and (t.min== 0))
{
  digitalWrite(LED, HIGH);
  delay (65000);
  digitalWrite(LED, LOW);
}
else
{digitalWrite (LED, LOW);
}

}
[/code]

Désolé je devais dormir à moitié à l'heure où j'ai écrit mon message... Il manquait une condition pour que ça fonctionne correctement, j'ai édité le code ( qui doit être mis dans loop(), même les déclarations des variables puisque secondes prends les valeurs actuellement stockées dans t )

Et oui, delay bloque tout le programme, il ne fais rien d'autre (à part les interruptions) qu'attendre que le delai se termine.

Une autre façon d'écrire mon code pour le même résultat :

if ( secondes >= secondesDepuisMinuit( 18, 0, 0 ) && secondes <= secondesDepuisMinuit( 19, 0, 0 ) )
{
  if ( etatLed == false )
  {
    allumerLed();
    etatLed = true;
  }
}
else if ( etatLed == true )
{
  eteindreLed();
  etatLed = false;
}

S'il n'y a que ça à faire, un arduino et une RTC (et un relais j'imagine que ce n'est pas la LED), vous avez aussi le Lot de 2 programmateurs 24 h mécanique à 6,50€ chez Leroy Merlin.... :wink:

Bonsoir,

Non en réalité ce que je compte faire est un peu plus complexe et implique d’autres actions ; gestion d’un Spa, filtration, commande des différentes pompes etc …

La partie commande manuelle m’a pas trop posé de problèmes en revanche la partie automatisée avec les routines…

La led c’était effectivement un exercice pour apprivoiser la RTC :wink:

OK donc il faudra éviter d'utiliser delay() sinon vous ne pourrez rien gérer d'autre.

➜ la programmation par machine à états (cf mon tuto éventuellement) permet de structurer le code pour ce genre de choses