Problème avec "now.dayOfTheWeek"

Bonjour.
Je viens vers vous avec un problème d'éclairage d'aquarium. Tout fonctionne correctement, allumage aux heures voulues,
commande des divers relais et autres rampes à leds. Mais justement, pour la gestion de l'éclairage, j'aimerai pouvoir faire une différence en fonction des jours de la semaine. J'ai essayé diverses formules avec "now.dayOfTheWeek ()" comme vous pouvez
le voir dans l'extrait de code que je joins ici :

#include <Wire.h>
#include <RTClib.h>
RTC_DS1307 RTC;

int ledR = 8;
int ledV = 9;
int ledB = 10;

int ledblanc1 = 11; // led blanche
int ledblanc2 = 12; // led blanche
int ledblanc3 = 13; // led blanche

int ledblanc4 = 44; // led blanche
int ledblanc5 = 45; // led blanche

int relaisCO2 = 50; //  co2 aquarium     digitalWrite

int relaisnouriture = 53; // nouriture   digitalWrite

int i = 255 ;  //intensité lumineuse (de 0 à 255 pour le maxi)
int dayOfTheWeek = dayOfTheWeek;
void setup()
{
  Wire.begin();
  RTC.begin();

  pinMode (ledR, OUTPUT);
  pinMode (ledV, OUTPUT);
  pinMode (ledB, OUTPUT);

  pinMode (ledblanc1, OUTPUT);
  pinMode (ledblanc2, OUTPUT);
  pinMode (ledblanc3, OUTPUT);
  pinMode (ledblanc4, OUTPUT);
  pinMode (ledblanc5, OUTPUT);

  pinMode (relaisCO2, OUTPUT);

  pinMode (relaisnouriture, OUTPUT);
}
void loop()
{


  // -----------------------------------------------------------------------------------------------------------------
  //                                   ALLUMAGE   LEVER JOUR   MATIN    9h00  SAMEDI ET DIMANCHE
  // ----------------------------------------------------------------------------------------------------------------

  DateTime now = RTC.now();
  if ((now.dayOfTheWeek () >= 0, 6) && (now.hour() >= 9) && (now.minute() >= 0) && (now.second() >= 0) && (now.dayOfTheWeek () <= 1, 2, 3, 4, 5))
  {
    for (i = 0; i <= 255; i++)  //
    {
      analogWrite (ledR, i);
      analogWrite (ledV, i * 0.2);

      delay (55);  //  1150 cycles pour atteindre i = 255 ==> +/= 5"
    }
    while (i = 255) //  i maximum
    {
      analogWrite (ledR, i);
      analogWrite (ledV, i * 0.2);


      // ----------------------------------------------------------------------------------------------------------------
      //                               ALLUMAGE   BLEU   MATIN    9h00       LUNDI À VENDREDI
      // ----------------------------------------------------------------------------------------------------------------

      if ((now.dayOfTheWeek () >= 1, 2, 3, 4, 5) && (now.hour() >= 9) && (now.minute() >= 0) && (now.second() >= 0) && (now.dayOfTheWeek () <= 0, 6))
      {
        for (i = 0; i <= 255; i++)  //
        {
          analogWrite (ledB, i);
          delay (55);  //  1150 cycles pour atteindre i = 255 ==> +/- = 5"    115 cycles pour +/- 1"
        }
        while (i = 255) //  i maximum
        {
          analogWrite (ledB, i);

        }
      }
    }
  }
}

Je pense que je loupe quelque chose. L'extrait que je donne ne tient pas compte de "now.dayOfTheWeek". Les deux éclairages s'allument l'un après l'autre, dans l'ordre du code et à l'heure voulue. Idem pour l'extinction (que je n'ai pas mis ici pour ne pas alourdir le code.
La question que je me pose : pourquoi "now.dayOfTheWeek" n'est pas pris en compte ?
Je ne doute pas que l'un d'entre vous aura trouvé le "bug". Merci à vous pour votre aide :wink:

D'abord, modifie ton message pour mettre tes lignes de code entre balises CODE (touche </> de l'éditeur)

dayOfTheWeek () est une fonction qui renvoie un byte (type uint8_t : de 0 à 255), qui varie ici de 0 à 6.
0 pour dimanche à 6 pour samedi.

Tes tests ne sont pas corrects :

now.dayOfTheWeek () >= 0,6 ne veut rien dire : que veux-tu faire ici ? dimanche ou samedi ?
now.dayOfTheWeek () == 0 || now.dayOfTheWeek () == 6

now.dayOfTheWeek () <= 1,2,3,4,5 devrait être now.dayOfTheWeek () <= 5

now.dayOfTheWeek () >= 1,2,3,4,5 devrait être now.dayOfTheWeek () !=0 && now.dayOfTheWeek () !=6
(!= veut dire différent de)

now.dayOfTheWeek () <= 0,6 je suppose que tu veux dire 'ni samedi, ni dimanche' ?
now.dayOfTheWeek () !=0 && now.dayOfTheWeek () !=6

Pour répondre plus précisément à ta question "pourquoi le test sur dayOfTheWeek n'est pas pris en compte" : je dirais que lorsque tu écris "now.dayOfTheWeek () >= 0,6", voyant la virgule le compilateur prend ça comme deux conditions avec un 'ou' entre les deux. Première condition now.dayOfTheWeek () >= 0 et la seconde est simplement 6. Or les booléens 'true' et 'false' sont des alias pour les chiffres 1 et 0 respectivement. De même tout nombre entier supérieur à 0 sera compris comme 'true' (1). Donc ta condition initiale sera vraie puisque 6 est vrai (puisque vaut aussi 1). Je pense que c'est une explication...

et merci de corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code]`` [color=blue]// votre code ici[/color] ``[/code].

ça doit ressembler à cela:// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l'IDE avant de copier le code pour qu'il soit indenté correctement)

une bonne habitude à prendre...

et merci de corrigez votre post ci dessus et rajoutez les code tags autour du code:

[code]

[color=blue]// votre code ici[/color]

[/code]

.

ça doit ressembler à cela:

// votre code ici

(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l'IDE avant de copier le code pour qu'il soit indenté correctement)

une bonne habitude à prendre...

lesept:
now.dayOfTheWeek () >= 0,6 ne veut rien dire : que veux-tu faire ici ? dimanche ou samedi ?

Pour répondre plus précisément à ta question "pourquoi le test sur dayOfTheWeek n'est pas pris en compte" : je dirais que lorsque tu écris "now.dayOfTheWeek () >= 0,6", voyant la virgule le compilateur prend ça comme deux conditions avec un 'ou' entre les deux. Première condition now.dayOfTheWeek () >= 0 et la seconde est simplement 6. Or les booléens 'true' et 'false' sont des alias pour les chiffres 1 et 0 respectivement. De même tout nombre entier supérieur à 0 sera compris comme 'true' (1). Donc ta condition initiale sera vraie puisque 6 est vrai (puisque vaut aussi 1). Je pense que c'est une explication...

Non ça ne marche pas comme cela. il n'y a pas de OU implicite.

Une expression composée de deux expressions séparées par une virgule est évaluée ainsi (cf comma operator): on évalue la premiere expression, on évalue la secode et l'expression composée prend la valeur retournée par la seconde expressions

par exemple si vous demandez x = (expression1, expression2); expression1 va être exécuté, puis expression2 et on mettra ce que retourne expression2 dans x

donc ici on a if (now.[color=red]dayOfTheWeek () >= 0[/color][color=blue],[/color][color=green]6[/color]) {.... la première expression est calculée, on compare bien dayOfTheWeek avec 0 mais on n'en fait rien (et comme ça n'a pas d'effet de bords il se peut même que le compilateur le vire) puis on évalue 6 qui vaut simplement 6 et donc c'est comme si on avait écrit

 dayOfTheWeek () >= 0;
if (6) {...

6 est promu en booléen à vrai et donc la condition est toujours vraie. Le compilateur est capable de voir cela dès la compilation donc peut virer le test et tout ce qui serait dans un else puisque ce ne sera jamais exécuté

J-M-L:
Une expression composée de deux expressions séparées par une virgule est évaluée ainsi (cf comma operator): on évalue la première expression, on évalue la seconde et l'expression composée prend la valeur retournée par la seconde expression

Merci, je ne me souvenais plus comment la première partie n'était pas prise en compte.

Bonjour
Tout d'abord merci de vos réponses et je vous prie de m'excuser pour la présentation de mon extrait de code. Je maitrise mal le système. Tout comme je maitrise mal (voire, très mal) le langage C++
Je fais des efforts pour comprendre, mais à plus de 70 ans et après des études littéraires, ce n'est pas évident du tout. Je compte sur votre indulgence et votre bienveillance et surtout vos conseils.
Je viens juste de lire vos réponses et je n'ai pas encore testé. Je m'y mets tout de suite et vous tiens au courant. Et encore merci (même si je me suis fais un peu tiré les oreilles :wink:

Après plus de deux heures passées dessus, ça ne marche toujours pas. Avec le code suivant, rien ne s'allume. Normal puisque nous sommes vendredi et non samedi ou dimanche. Cette condition n'étant pas remplie, je pensais (à tord visiblement) que ce serait la partie suivante qui prendrait la suite et donc que l'allumage bleu se mettrait en marche. Mais non. Si j'inverse "lever jour samedi et dimanche" avec "allumage bleu", après compilation, le bleu s'allume et "lever jour" ne s'allume pas.
J'en déduit donc qu'en fait, c'est la première commande qui est prioritaire et bloque la suite du processus. Comment faire pour que la première instruction ne bloque pas les suivantes si elle n'est pas remplie ?
C'est dur le C++ ...

                                 ALLUMAGE   LEVER JOUR   MATIN    5h00  SAMEDI ET DIMANCHE
  // ----------------------------------------------------------------------------------------------------------------

  DateTime now = RTC.now();
  if ((now.dayOfTheWeek () == 0 && now.dayOfTheWeek () == 6) && (now.hour() >= 5) && 
(now.minute() >= 0) && (now.second() >= 0 ))
  {
    for (i = 0; i <= 255; i++)  //
    {
      analogWrite (ledR, i);
      analogWrite (ledV, i * 0.2);

      delay (55);  //  1150 cycles pour atteindre i = 255 ==> +/= 5"
    }
    while (i = 255) //  i maximum
    {
      analogWrite (ledR, i);
      analogWrite (ledV, i * 0.2);

      // -----------------------------------------------------------------------------------------------------------------
      //                               ALLUMAGE   BLEU   MATIN    5h00   DU LUNDI AU VENDREDI
      // -----------------------------------------------------------------------------------------------------------------

      if ((now.dayOfTheWeek () == 1 && now.dayOfTheWeek () == 2 && now.dayOfTheWeek () == 3 && now.dayOfTheWeek () == 4 && now.dayOfTheWeek () == 5)
          && (now.hour() >= 5) && (now.minute() >= 0) && (now.second() >= 0))
      {
        for (i = 0; i <= 255; i++)  //
        {
          analogWrite (ledB, i);
          delay (55);  //  1150 cycles pour atteindre i = 255 ==> +/- = 5"    115 cycles pour +/- 1"
        }
        while (i = 255) //  i maximum
        {
          analogWrite (ledB, i);

&& veut dire 'et'. La condition

now.dayOfTheWeek () == 0 && now.dayOfTheWeek () == 6

ne peut pas être vérifiée, un nombre ne peut pas être égal à 0 et à 6.

Pour un 'ou' il faut utiliser ||

now.dayOfTheWeek () == 0 || now.dayOfTheWeek () == 6

De même pour les autres conditions...

Essayez d’abord d’écrire toutes vos conditions en français

Si on est lundi OU vendredi ET qu’il est plus de 14h ET moins de 22h alors....

Ça vous permettra de voir où mettre des && pour les ET ainsi que des || pour les OU et grouper ensuite avec des parenthèses ce qui va ensemble

Pour l’exemple ci dessus

 if (
    ((now.dayOfTheWeek () == 0) || (now.dayOfTheWeek () == 4)) // si lundi est 0
  && 
    ((now.hour() >= 14) && (now.hour() <= 22))
  ) {…}

Je pense que pour simplifier la lecture et améliorer la maintenabilité ce serait une bonne chose de séparer les conditions jour et heure.

Je me demande si dans ce cas là un switch ... case ne serait plus lisible
Le switch.. case détermine le fonctionnement particulier liés aux jours.
Les fonctions appelées vont gérer les conditions liées aux horaires

swtich(now.dayOfTheWeek()){
       case 0:
       case 1:
            fonction1();
            break;
      case 2:
      case 3:
      case 4:
           fonction2();
           break;
      default:
           fonctionParDefaut();
}
}

J'ai essayé toutes les propositions que vous m'avez faites, mais aucune ne fonctionne en prenant en compte les jours de la semaine. C'est toujours la première fonction qui démarre, suivie de la seconde, quelque soit le jour de la semaine choisi.
Je pense que je vais m'en tenir à ma première version et que tous les jours l'éclairage démarrera progressivement à 11h00 et s'éteindra de la même manière tous les jours à 21h30. Dommage, j'aurai aimé un allumage plus long le week-end pour "profiter" plus longtemps de l'aquarium allumé.
En tout cas, encore merci pour vos tentatives pour m'aider, mais l'élève n'est pas très doué :wink:

On va y arriver, n'abandonne pas. Quelles sont les plages horaires et les jours ? Comment sais-tu que ça ne marche pas ?

Vous avez vérifié que le No du jour est bien retourné ?

Le sept, merci pour tes encouragements.
Le principe est simple : tous les jours à 11h00, des leds bleues sont allumées pour simuler la nuit, puis se sont des RGB qui prennent le relais pour simuler le lever du soleil, viennent ensuite des leds blanches pour le jour, ensuite, c’est l’extinction des leds bleues et RGB. On est donc en plein jour.
Pour le soir, à 21h30, allumage des leds bleues et RGB, puis extinction des leds blanches, extinction des RGB puis des bleues. Toutes ces opérations se font progressivement sur une durée d’une minute. Jusque là tout va bien.
Ce que j’aimerai, c’est que le samedi et le dimanche l’amplitude d’éclairage soit plus longue pour pouvoir profiter de l’aquarium, par exemple entre 9h00 et 22h30. Et c’est ici que commencent les problèmes et mon histoire de "now.dayOfTheWeek" que je ne parviens pas à mettre en place. Quelle que soit la valeur donnée, par exemple : "((now.dayOfTheWeek () == 0) || (now.dayOfTheWeek () == 6))" pour dimanche et samedi, le programme n’en tient pas compte.
Et c’est là que je m’arrache les derniers cheveux qui me restent :wink:

J-M-L:
Vous avez vérifié que le No du jour est bien retourné ?

Je ne suis pas très expert. Le N° de jour doit être retourné où ?

Bon, j'ai pitié de ton coiffeur, qui va faire faillite si je ne t'aide pas...

D'abord, crée une variable 'jour' dans laquelle tu stockes la valeur de now.dayOfTheWeek ()
De même, crée des variables 'heures' et 'minutes'. C'est plus facile à lire si tu écris tes conditions avec des mots clés plus faciles.

Ensuite, crées des variables d'état pour les leds bleues et les leds blanches, en déclarant ceci dans l'en-tête du code:

byte heures = 0;
byte minutes = 0;
byte jour = 255;
bool leds_bleues = false;
bool leds_blanches = false;

On va organiser la loop en trois parties :

  • on lit l'heure et le jour
  • on fait les tests pour mettre à jour les états des leds
  • on allume les leds selon leur état

Pour tester les heures - minutes, il existe plusieurs solutions. Moi je préfère calculer un résultat intermédiaire : le nombre de minutes écoulées depuis minuit. Ce nombre vaut bien sûr : heures*60+minutes

C'est plus facile de comparer ça plutôt que de comparer les heures et les minutes.
Dans ton cas, on va déclarer 8 constantes qui seront tes instants d'allumage et d’extinction des leds bleues et blanches, en semaine et en weekend. Ceci va aussi dans l'en-tête :

const int allumBleuSem = 21*60+30;
const int extBleuSem = ...
etc.

Je te laisse faire les calculs car j'ai un peu de mal à suivre ton besoin.

Ensuite la loop.
Partie 1: on lit l'heure et le jour

jour = now.dayOfTheWeek ();
heures = now.hour();
minutes = now.minutes(); // vérifier s'il y a un 's' ou non
int maintenant = heures*60+minutes;

Partie 2 : les tests
D'abord mettre les états à false (pour être sûr de ne rien laisser allumé)

leds_bleues = false;
leds_blanches = false;

Ensuite, un exemple

Ce que j'aimerais, c'est que le samedi et le dimanche l'amplitude d'éclairage soit plus longue pour pouvoir profiter de l'aquarium, par exemple entre 9h00 et 22h30

if (jour == 0 || jour == 6) { // samedi ou dimanche
if (maintenant > allumBlancWE && maintenant < extBlancWE) leds_blanches = true;
}

Il suffit de faire la même chose pour les autres conditions.

Partie 3 : allumage des leds selon leur état
Le plus simple c'est de les éteindre toutes et d'allumer ce qui doit l'être

// ici les lignes pour éteindre les leds bleues
// ici les lignes pour éteindre les leds blanches
if (led_bleues) {
// ici les lignes pour allumer les leds bleues
}
if (led_blanches) {
// ici les lignes pour allumer les leds blanches
}

Ce n'est pas optimal, je sais (ça fait même un peu mal aux yeux) mais pour l'instant c'est le plus simple. Sinon, il faudrait conserver l'état précédent et comparer avec le nouvel état pour savoir si on éteint ou si on allume...

Voila, je te laisse avancer de ton côté, j'espère que c'est compréhensible, sinon je peux essayer d'expliquer mieux.

On verra ensuite pour faire l'allumage progressif. Il faut d'abord que cette version fonctionne.

Bernard-Sarlat:
J'ai essayé toutes les propositions que vous m'avez faites, mais aucune ne fonctionne en prenant en compte les jours de la semaine.

avant de baisser les bras, essayez déjà ce petit code en ouvrant le moniteur Série à 115200 bauds.

#include <RTClib.h>
RTC_DS1307 rtc;

const char* jours[] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
const char* mois[] = {"janvier", "fevrier", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"};

void setup()
{
  Serial.begin(115200);

  if (! rtc.begin()) {
    Serial.println(F("RTC absente"));
    while (true); // on meurt ici, boucle sans fin
  }

  if (! rtc.isrunning()) {
    Serial.println(F("RTC NON INITIALISEE"));
    // on la met à l'heure de dernière compilation
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  DateTime maintenant = rtc.now();

  Serial.println(F("Numero du jour = "));
  Serial.println(maintenant.dayOfTheWeek());
  Serial.println(F("Numero du mois = "));
  Serial.println(maintenant.month());

  Serial.print(jours[maintenant.dayOfTheWeek()]);
  Serial.write(' ');
  Serial.print(maintenant.day());
  Serial.write(' ');
  Serial.print(mois[maintenant.month() - 1]);
  Serial.write(' ');
  Serial.print(maintenant.year());
  Serial.print(F(", il est "));
  Serial.print(maintenant.hour());
  Serial.print(F(" heures, "));
  Serial.print(maintenant.minute());
  Serial.print(F(" minutes et "));
  Serial.print(maintenant.second());
  Serial.println(F(" secondes"));
}

void loop() {}

--> que voyez vous dans la console ?