[Résolu - Merci beaucoup :) ] TaskMe - Mon gestionnaire de tâches ménagères

Je ne peux donc plus trier les tâches pour les attribuer si

l'idée c'était le tableau d'actions qui lui sera dynamique - on ne conserve que les indices des tâches.

const uint8_t nbActions = nbTaches; // on pourrait en avoir plus
struct t_action {
  uint8_t indexTache;
  uint8_t indexIndividu;
  bool effectuee;
} actions[nbActions];

D'accord, d'où la diminution d'espace de stockage dynamique :o

J'vais continuer de me pencher dessus, j'avoue ne pas avoir encore tout compris à l'exemple :slight_smile:

Merci de prendre autant de temps pour m'aider :slight_smile:

au final "laver la vaisselle" c'est toujours la même chose donc on décrit cette chose une seule fois en fonction de la structure en rangeant cela dans le tableau des tâches

struct t_tache {
  const char * nom;
  const uint8_t duree;
  const uint8_t difficulte;
  bool recurente;
  t_jour jour;
} taches[] = {
  {"Vaisselle", 1, 1, true, Lundi},
...

(je ne sais pas trop ce que vous voulez faire avec récurrente, j'ai mis cela comme un booléen)

comme on l'a mis à l'indice 0 du tableau (premier élément du tableau) si on veut enregistrer une action de faire la vaisselle, il suffit de dire que la description de l'action est à cet indice 0 --> comme vous avez moins de 255 tâches différentes, on peut stocker cet indice sur un seul octet (type uint8_t ou byte) et donc avec 1 seul octet on sait tout ce qu'il faut savoir sur la tâche

la même chose s'applique pour les personnes. on a un tableau des individus.

 struct t_individu {
  const char * nom;
} individus[] = {{"William"},{"Adam"}};

Quand on affecte une action à un individu, au lieu de dupliquer le nom de la personne, on conserve uniquement l'indice dans le tableau des individus

Donc si je crée une action avec 0 et 0 comme paramètres, je sais que c'est pour la vaisselle et que c'est William qui doit la faire.

D'accord, je commence à comprendre tout doucement , mais sûrement ! :slight_smile:

Pour le membre récurrence, il s'agissait d'un entier pour initialiser mon tableau de jour. Si la vaisselle doit être faite 3 fois par semaine je créais encore un tableau dynamique pour les entier 0,2,4 correspondant à Lundi Mercredi Vendredi.

Une autre question :-/ (enfin plusieurs finalement)
Comment faire pour garder en mémoire tout ça ? Je compte alimenter mon Arduino via une pile et j'ai pensé qu'un interrupteur ne serait pas de refus pour ne pas consommer toute la pile en 2 jours.
D'abord à chaque allumage, l'Arduino repasse dans le setup et réinitialise non ?
Si je le passe en commentaire ça devrait peut être fonctionner ?
Je ne sais pas si je suis très clair, désolé pour ça, je commence à m'embrouiller :slight_smile:

Pour le membre récurrence, il s'agissait d'un entier pour initialiser mon tableau de jour. Si la vaisselle doit être faite 3 fois par semaine je créais encore un tableau dynamique pour les entier 0,2,4 correspondant à Lundi Mercredi Vendredi.

OK donc un bool n'était pas approprié. une façon peu gourmande serait de définir les jours sous forme de champs de bit : un octet c'est 8 bits, donc on a assez de bits pour faire les 7 jours

par exemple récurrence pourrait correspondre en binaire à 0DSVJMML (jours de la semaine) et si vous avez un 1 dans un bit c'est que la tâche se fait ce jour là par exemple 0b00000001 ça veut dire que le lundi, ou 0b00001111 ça veut dire Lundi, Mardi, Mercredi et Jeudi

comme on a l'enum qui a Lundi qui vaut 0, Mardi qui vaut 1 etc on peut fabriquer une octet en utilisant un OU logique (|) et la fonction bit()

byte jourActifs = bit(Lundi); // que le lundi
byte jourActifs = bit(Lundi) | bit(Jeudi); // le lundi et le jeudi
....

Hooo, je ne connaissais pas nous plus. Ca semble pourtant logique, surtout pour un programme informatique ...
Je vais essayer de me renseigner dessus demain.

J'ai également rencontrer un nouveau problème (ça n'en fini plus :'()
Dans mon ancien programme, j'ai déclaré un entier (du coup uint8_t ferais l'affaire de ce que j'ai compris :slight_smile: ) appelé Indice que j'incrémentais à chaque fois que j'appuyais sur un bouton. Mes tâches du jours étant sous la forme d'une liste je pouvais alors facilement accéder aux différentes tâches de la journée. Mais avec le système de structure je n'ai pas trouvé de solution. Je suis repartie sur la création d'une liste dynamique, ce qui ne me semble pas être judicieux, surtout que je fais des boucles simplement pour récupérer le nombre de tâche de la journée. De plus il semble y avoir un problème de copie, les individus portent entres autres des noms chinois :astonished:.
Mon problème se situe donc dans le loop pour accéder aux tâches de la journée. Sachant que j'ai un second bouton qui doit également me permettre de passer la tâche comme étant effectuée, la liste semble, dans ma tête, la méthode la plus simple (Bon après y'a pas vraiment beaucoup de possibilité dans cette fameuse tête actuellement :roll_eyes: :sweat_smile:). Si vous avez une solution je suis tout ouïe :slight_smile:

Si vous regardez le premier code posté j’imprimais les tâches par jour (sans tenir compte de la récurrence). Parcourir un tableau est rapide

J'ai trouvé super intéressant le type byte. Par contre je ne suis pas sûr de bien comprendre comment l'utiliser pour la gestion des jours. Ce qui me semble le plus adéquat d'après mes recherches serait l'utilisation de masque.

Admettons taskday = 0b 0000 1001 = 9 en entier non signé qui équivaut à Lundi et Jeudi.

Mon masque serait pour Lundi : 0b 0000 0001.

Il faut ensuite que j'effectue l'opération &, ce qui devrait me donner :
0000 1001 & 0000 0001 = 0000 0001

La condition serait donc byte taskDay & byte maskDay == maskDay ?

Est-ce correct ?

Edit : Ca fonctionne !

oui, il n'y a même pas besoin de faire == maskDay puisque le masque ne contient qu'un seul 1 au bon endroit; si l'octet résultat du masque n'est pas nul alors c'est qu'il y avait un 1 au bon endroit.

byte maskLundi = 0b00000001;
byte recurence  = 0b01001001; // Lundi, Jeudi; Dimanche
if (recurence & maskLundi) {
  // le lundi était bien dans la liste des jours
  ...
}

si vous vouliez testez pour 2 jours alors effectivement il faudrait faire ==

byte maskLundiJeudi = 0b00001001;
byte recurence  = 0b01001001; // Lundi, Jeudi; Dimanche
if ((recurence & maskLundiJeudi) == maskLundiJeudi) {
  // le lundi et Jeudi étaient bien dans la liste des jours
  ...
}

si vous vouliez testez un ou entre plusieurs jours alors pas besoin non plus du ==

byte maskLundiJeudi = 0b00001001;
byte recurence  = 0b01001001; // Lundi, Jeudi; Dimanche
if (recurence & maskLundiETJeudi) {
  // le lundi ou le Jeudi étaient bien dans la liste des jours
  ...
}

Notez que si vous définissez l'enum ainsi

enum t_jour : uint8_t {Dimanche = 1, Lundi = 2, Mardi = 4, Mercredi = 8, Jeudi = 16, Vendredi = 32, Samedi = 64, JourIgnore = 128};
const char* jours[] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};

vous avez directement les bonnes valeurs et donc vous pourriez écrire la définition des tâches avec des OU sans appeler bit()

struct t_tache {
  const char * nom;
  const uint8_t duree;
  const uint8_t difficulte;
  uint8_t jours;
} taches[] = {
  {"Vaisselle", 1, 1, Lundi | Mardi | Mercredi | Vendredi | Dimanche},
  {"Table", 1, 1, Samedi },
  {"Bar", 1, 1, Mardi },
  {"Balais", 1, 2, Mardi | Samedi },
  {"Serpillere", 1, 2, Samedi },
  {"Toilette", 7, 3, Samedi },
  {"Douche", 5, 2, Lundi | Mardi },
  {"Lavabo", 2, 1, Jeudi },
  {"Table basse", 4, 1, Mardi | Samedi },
  {"Tele", 1, 1, Samedi },
  {"Tapis", 10, 3 , Samedi },
  {"Sortir poubelle", 5, 3, Mardi | Dimanche },
  {"Rentrer poubelle", 5, 3, Mercredi | Lundi }
};

Notez que J'ai mis le dimanche en premier parce que les RTC généralement ont le dimanche comme jour. Si vous voulez afficher le texte correspondant à un jour, on ne peut plus directement utiliser l'enum comme index (puisqu'ils valent 1,2,4,8,16,32....) il faut lire la position du 1 pour savoir quel est l'index. Il y a une fonction du compilateur qui vous dit cela: la fonction __builtin_ctz() qui compte le nombre de 0 à droite de l'octet. Donc par exemple pour afficher le texte "Lundi" vous feriezSerial.println(jours[__builtin_ctz(Lundi)]);

Ce système est beaucoup mieux ! Je commençais en initialisant le jour de mes tâches en hexadécimal, maintenant c'est beaucoup plus lisible, et plus simple à initialiser si je souhaite rajouter des tâches :slight_smile:

J'ai un dernier problème malheureusement lorsque j'initialise le jour sur TUESDAY.
Ce sont les tâches où Mercredi fait partie des jours et non Mardi qui sont prises en compte.
Je n'arrive pas à trouver l'erreur, les bytes associés à Mardi et Mercredi semblent bon :confused:

Voici mon nouveau code :

#include <LiquidCrystal.h>
#include <DS1302.h>

DS1302 rtc(8, 10, 11);
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

  int memoireboutonScroll=1;
  int boutonScroll=9;

  int memoireboutonTask=1;
  int boutonTask=12;
  
  uint8_t nbindiceday=0;
  uint8_t* Indice;
  uint8_t indice=0; // Pour parcourir Indice[]
  
  int flagaff=false;
  char* memoireday;

  int etatboutonScroll; // Déclaration pour pouvoir l'utiliser dans la fonction Défiler

  int IntDay(String DAY){
  if(DAY=="Monday"){return 0;}
  if(DAY=="Tueday"){return 1;}
  if(DAY=="Wednesday"){return 2;}
  if(DAY=="Thursday"){return 3;}
  if(DAY=="Friday"){return 4;}
  if(DAY=="Saturday"){return 5;}
  if(DAY=="Sunday"){return 6;}
}
char* FrDay(String DAY){
  if(DAY=="Monday"){return "Lundi";}
  if(DAY=="Tuesday"){return "Mardi";}
  if(DAY=="Wednesday"){return "Mercredi";}
  if(DAY=="Thursday"){return "Jeudi";}
  if(DAY=="Friday"){return "Vendredi";}
  if(DAY=="Saturday"){return "Samedi";}
  if(DAY=="Sunday"){return "Dimanche";}
}

enum t_jour : uint8_t {Lundi = 1, Mardi = 2, Mercredi = 4, Jeudi = 8, Vendredi = 16, Samedi = 32, Dimanche = 64, };
const char* jours[7] = {"Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"};
uint8_t maskDay[7]={0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000};

struct t_task{
  const char* cName;
  const t_jour bDay;
}task[]={
  {"Laver Vaisselle",Lundi | Mercredi | Vendredi | Dimanche },
  {"Balais",Samedi},
  {"Serpillere",Samedi},
  {"Tapis",Dimanche},
  {"Toilette",Samedi},
  {"Jeter Poubelles",Dimanche | Vendredi | Mardi},
  {"Sortir Poubelles",Mardi},
  {"Rentrer Poubelles",Mercredi},
  {"Douche",Samedi},
  {"Bar", Lundi | Mercredi | Vendredi | Dimanche},
  {"Plan Travail", Lundi | Mercredi | Vendredi | Dimanche},
  {"Ranger Vaisselle", Lundi | Mercredi | Vendredi | Dimanche},
  {"Table", Dimanche | Vendredi | Mercredi},
  {"Table Basse", Lundi | Mardi | Mercredi | Jeudi | Vendredi | Samedi | Dimanche},
  {"Lavabo",Samedi},
  {"Tele",Dimanche}
};
const uint8_t nbtask=sizeof task / sizeof task[0];

struct t_indiv{
  const char* cName;
}individus[]={{"William"},{"Adam"}};
const uint8_t nbindividu=sizeof individus/sizeof individus[0];

struct t_coord{
  uint8_t indexIndividu;
  uint8_t indexTask;
  bool realisee;
}coord[nbtask];

void initCoord(){
  for (uint8_t i=0;i<nbtask;i++){
    coord[i].indexTask=i%nbtask;
    coord[i].realisee=false;
  }
}

void affectationIndividu(){
  uint8_t individu=0;
  for(uint8_t i=0;i<nbtask;i++){
    coord[i].indexIndividu=individu;
    individu=(individu+1)%nbindividu;
  }
}

void attribNewIndividu(uint8_t indice){
  coord[indice].indexIndividu=(coord[indice].indexIndividu + 1)%nbindividu;
}

void attribPrcdtIndividu(uint8_t indice){
  coord[indice].indexIndividu=(coord[indice].indexIndividu + (nbindividu-1)) % nbindividu;
}

void bascRealisee(uint8_t indice){
  coord[indice].realisee=1-coord[indice].realisee;
}

void Ajout(uint8_t n){
  uint8_t tableau[nbindiceday];
  for(uint8_t i=0;i<nbindiceday-1;i++){
    tableau[i]=Indice[i];
  }
  tableau[nbindiceday-1]=n;
  delete[] Indice;
  Indice=new uint8_t[nbindiceday];
  for(uint8_t i=0;i<nbindiceday;i++){
    Indice[i]=tableau[i];
  }
}

void initIndice(){
  nbindiceday=0;
  for (int n=0;n<nbtask;n++){
      if((task[coord[n].indexTask].bDay & maskDay[IntDay(rtc.getDOWStr())]) == maskDay[IntDay(rtc.getDOWStr())]){
        nbindiceday++;
        Ajout(n);
      }
  }
}

void AfficheTest(){
  for (int i=0;i<7;i++){
    Serial.print(jours[i]);Serial.println(" :");
    for (int n=0;n<nbtask;n++){
      if((task[coord[n].indexTask].bDay & maskDay[i]) == maskDay[i]){
        Serial.print("\tTask name : "); Serial.print(task[coord[n].indexTask].cName);
        Serial.print("          ");
        Serial.print("\tTask indiv : ");Serial.println(individus[coord[n].indexIndividu].cName);
        attribNewIndividu(n);
      }
    }
  }
}

void Defiler(uint8_t taille){     // Fonction permettant de faire défiler le texte si celui-ci dépasse 16 caractères
  uint8_t ind=0;
  char ligne[taille];
  for(uint8_t i=0;i<strlen(task[coord[Indice[indice]].indexTask].cName);i++){
      ligne[i]=task[coord[Indice[indice]].indexTask].cName[i];
  }
  ligne[strlen(task[coord[Indice[indice]].indexTask].cName)]=' ';
  ligne[strlen(task[coord[Indice[indice]].indexTask].cName)+ 1]='-';
  ligne[strlen(task[coord[Indice[indice]].indexTask].cName)+ 2]=' ';
  for(uint8_t i=(strlen(task[coord[Indice[indice]].indexTask].cName)+3);i<taille;i++){
    ligne[i]=individus[coord[Indice[indice]].indexIndividu].cName[i-(strlen(task[coord[Indice[indice]].indexTask].cName)+3)];
  }

  Serial.println(ligne);
  
  for(uint8_t i=0;i< (taille%16 + 1);i++){
    lcd.setCursor(0,1);
    lcd.print("                ");
    lcd.setCursor(0,1);
    for (uint8_t j=ind;j<16+ind;j++){
      lcd.print(ligne[j]);
    }
    delay(200);
    ind++;
    if (etatboutonScroll!=memoireboutonScroll && etatboutonScroll==LOW){
    indice=(indice+1)%nbindiceday;
    flagaff = false;
    return;
  }
  memoireboutonScroll=etatboutonScroll;
  }
  delay(100);
  lcd.setCursor(0,1);
  lcd.print(ligne);
}

void AfficheDone(){
  uint8_t taille = strlen(FrDay(rtc.getDOWStr())) + 3;
  if(coord[Indice[indice]].realisee == true){
    lcd.setCursor(taille,0);
    lcd.print("Done");
  }
  else{
    lcd.setCursor(taille,0);
    lcd.print("     ");
  }
}

void AfficheTask(){
  if(flagaff==false)
  {
    uint8_t taille=strlen(task[coord[Indice[indice]].indexTask].cName)+3+strlen(individus[coord[Indice[indice]].indexIndividu].cName);
    if(taille>16){
      Serial.print("Taille : ");Serial.println(taille);
      Defiler(taille);
    }
    else{
      lcd.setCursor(0,1);
       lcd.print("                ");
      lcd.setCursor(0,1);
      lcd.print(task[coord[Indice[indice]].indexTask].cName);
      lcd.print(" - ");
      if(coord[Indice[indice]].realisee==true){
        lcd.print(individus[(coord[Indice[indice]].indexIndividu + (nbindividu-1)) % nbindividu].cName);
      }
      else{
        lcd.print(individus[coord[Indice[indice]].indexIndividu].cName);
      }
    }
    flagaff=true;
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(boutonScroll,INPUT_PULLUP);
  pinMode(boutonTask,INPUT_PULLUP);
  rtc.halt(false);
  rtc.writeProtect(false);
  
  rtc.setDOW(TUESDAY);
  rtc.setTime(20, 10, 00);    //// Set the time to 12:00:00 (24hr format)
  rtc.setDate(3, 23, 2021);   // Set the date to August 6th, 2010*/
  
  initCoord();
  affectationIndividu();
  
  lcd.begin(16, 2);
  analogWrite(8,15);

  Serial.println((task[coord[0].indexTask].bDay & maskDay[IntDay(rtc.getDOWStr())]) == maskDay[IntDay(rtc.getDOWStr())]);
}

void loop() {

for(int i=0;i<nbindiceday;i++ ){
  Serial.print(Indice[i]);
}
Serial.println();

  
  // Réinitialisation le jour suivant
  if(memoireday!=FrDay(rtc.getDOWStr())){
    for (int i=0;i<nbtask;i++){
      if(coord[i].realisee==true){
        coord[i].realisee=false;
      }
    }
    delete [] Indice;
  }
  memoireday=FrDay(rtc.getDOWStr());

  // Initialisation liste Indice

  initIndice();

  // Affichage du jour
  lcd.setCursor(0,0);
  lcd.print(FrDay(rtc.getDOWStr()));
  lcd.print(" : ");
  
  /*
  if(flagaff==false){
    AfficheTest();
  }
  */
  // Affichage de la tâche
  AfficheTask();
  AfficheDone();

  // Partie bouton
  int etatboutonScroll = digitalRead(boutonScroll);
  int etatboutonTask = digitalRead(boutonTask);

  if (etatboutonScroll!=memoireboutonScroll && etatboutonScroll==LOW){
    indice=(indice+1)%nbindiceday;
    flagaff = false;
  }
  memoireboutonScroll=etatboutonScroll;

   if (etatboutonTask!=memoireboutonTask && etatboutonTask==LOW)
  {
    if(coord[Indice[indice]].realisee == false){
      bascRealisee(Indice[indice]);
      attribNewIndividu(Indice[indice]);
    }
    else{
      bascRealisee(Indice[indice]);
      attribPrcdtIndividu(Indice[indice]);
    }
  }

  memoireboutonTask=etatboutonTask;

}

Edit : Après des tests, les jours retenus le mardi ne sont pas ce du mercredi. Dans la liste, il s'agit des tâches ;
{0,9,10,11,13} donc les tâches avec plusieurs jours...

Pour un petit problème comme ça vous pouvez hésiter entre des structures (struct) et des classes (class). Tant qu'on n'utilise pas les constructions un peu compliquées de la programmation orientée objet (héritage, polymorphisme, etc.) l'avantage de l'une ou l'autre méthode n'est pas flagrant. En fait, pour faire simple une classe est la réunion d'une structure de données (struct) et de fonctions qui travaillent sur ces structures. Le mécanisme permet d'une part de simplifier l'écriture des dites fonctions (pas besoin de leur passer un pointeur sur une structure en paramètre) et d'autre part de sécuriser l'accès aux données : vous l'avez bien compris puisque vous avez écrit des "accesseurs" pour vos données. Mais ce n'est pas une obligation, on peut rendre les données publiques et, dans les petites applis à un seul programmeur, ça se fait souvent.

Personnellement, je vous encouragerais à écrire votre appli en utilisant des classes, car c'est le premier pas vers l'écriture d'appli bien plus complexe en poo. Même si pour votre histoire de taches ménagères c'est un peu le marteau pour écraser la mouche. J'irais même jusqu'à vous encourager à regarder ce que sont les classes génériques (c'est moins clean en C++ qu'en java, mais enfin...), et par exemple faire en sorte que vos "Ctask" héritent d'une classe NodeList d'une bibliothèque de listes génériques et les objets qui regroupent plusieurs taches héritent de la classe List.

Vous pourrez ainsi écrire par exemple, en utilisant des fonctions standard de ces bibliothèques :
tourDeVaisselle.add (paul) ;
aspirateur.remove (denise) ;
Notez que la seconde fonction suppose d'avoir des listes à double chainage. A vous de voir comment c'est fait et à quoi ça sert.

J'ai effectivement découvert très récemment et pas de manière approfondie la généricité en cours, je ne me sentais donc pas vraiment à l'aise à l'idée de les utiliser :slight_smile: Et je ne pense pas les approfondir plus que ça en cours pour le moment, étant passé sur Qt.

De ce que j'ai compris, les structures sont des classes simples dont les données membres sont publiques, c'est bien ça ?

L'écriture d'appli m'intéresse également beaucoup, mais je manque encore de temps pour que ce soit à ma porter sous peu :confused: d'ici quelques mois pourquoi pas ! :slight_smile:

Edit : J'ai beau tester pour le byte Mardi, rien ne s'améliore…

uint8_t maskDay[7]={0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000};

J'ai créé une liste pour sélectionner les tâches de la journée (elle enregistre les indices des tâches)
lorsque j'affiche cette liste j'obtient pour TUESDAY :

0, 9, 10, 11, 13,

Ce qui ne correspond absolument pas à mes données :

struct t_task{
  const char* cName;
  const t_jour bDay;
}task[]={
  {"Laver Vaisselle",Lundi | Mercredi | Vendredi | Dimanche},
  {"Balais",Samedi},
  {"Serpillere",Samedi},
  {"Toilette",Samedi},
  {"Tapis",Dimanche},
  {"Jeter Poubelles", Dimanche | Vendredi | Mardi},
  {"Sortir Poubelles",Mardi},
  {"Rentrer Poubelles",Mercredi},
  {"Douche",Samedi},
  {"Bar", Lundi | Mercredi | Vendredi | Dimanche},
  {"Plan Travail", Lundi | Mercredi | Vendredi | Dimanche},
  {"Ranger Vaisselle", Lundi | Mercredi | Vendredi | Dimanche},
  {"Table", Dimanche | Vendredi | Mercredi},
  {"Table Basse", Lundi | Mardi | Mercredi | Jeudi | Vendredi | Samedi | Dimanche},
  {"Lavabo",Samedi},
  {"Tele",Dimanche}
};

Il s'agit du dernier point à résoudre pour terminer le programme de mon projet :cry:

Postez le code...

Il était sur la page avant :slight_smile:

Le revoici, j'ai repris votre exemple à ma "sauce" pour tout comprendre

#include <LiquidCrystal.h>
#include <DS1302.h>

DS1302 rtc(8, 10, 11);
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

  int memoireboutonScroll=1;
  int boutonScroll=9;

  int memoireboutonTask=1;
  int boutonTask=12;
  
  uint8_t nbindiceday=0;
  uint8_t* Indice;
  uint8_t indice=0; // Pour parcourir Indice[]
  
  int flagaff=false;
  char* memoireday;

  int etatboutonScroll; // Déclaration pour pouvoir l'utiliser dans la fonction Défiler

  int IntDay(String DAY){
  if(DAY=="Monday"){return 0;}
  if(DAY=="Tueday"){return 1;}
  if(DAY=="Wednesday"){return 2;}
  if(DAY=="Thursday"){return 3;}
  if(DAY=="Friday"){return 4;}
  if(DAY=="Saturday"){return 5;}
  if(DAY=="Sunday"){return 6;}
}
char* FrDay(String DAY){
  if(DAY=="Monday"){return "Lundi";}
  if(DAY=="Tuesday"){return "Mardi";}
  if(DAY=="Wednesday"){return "Mercredi";}
  if(DAY=="Thursday"){return "Jeudi";}
  if(DAY=="Friday"){return "Vendredi";}
  if(DAY=="Saturday"){return "Samedi";}
  if(DAY=="Sunday"){return "Dimanche";}
}

enum t_jour : uint8_t {Lundi = 1, Mardi = 2, Mercredi = 4, Jeudi = 8, Vendredi = 16, Samedi = 32, Dimanche = 64, };
const char* jours[7] = {"Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"};
uint8_t maskDay[7]={0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000};

struct t_task{
  const char* cName;
  const t_jour bDay;
}task[]={
  {"Laver Vaisselle",Lundi | Mercredi | Vendredi | Dimanche},
  {"Balais",Samedi},
  {"Serpillere",Samedi},
  {"Toilette",Samedi},
  {"Tapis",Dimanche},
  {"Jeter Poubelles", Dimanche | Vendredi | Mardi},
  {"Sortir Poubelles",Mardi},
  {"Rentrer Poubelles",Mercredi},
  {"Douche",Samedi},
  {"Bar", Lundi | Mercredi | Vendredi | Dimanche},
  {"Plan Travail", Lundi | Mercredi | Vendredi | Dimanche},
  {"Ranger Vaisselle", Lundi | Mercredi | Vendredi | Dimanche},
  {"Table", Dimanche | Vendredi | Mercredi},
  {"Table Basse", Lundi | Mardi | Mercredi | Jeudi | Vendredi | Samedi | Dimanche},
  {"Lavabo",Samedi},
  {"Tele",Dimanche}
};
const uint8_t nbtask=sizeof task / sizeof task[0];

struct t_indiv{
  const char* cName;
}individus[]={{"William"},{"Adam"}};
const uint8_t nbindividu=sizeof individus/sizeof individus[0];

struct t_coord{
  uint8_t indexIndividu;
  uint8_t indexTask;
  bool realisee;
}coord[nbtask];

void initCoord(){
  for (uint8_t i=0;i<nbtask;i++){
    coord[i].indexTask=i%nbtask;
    coord[i].realisee=false;
  }
}

void affectationIndividu(){
  uint8_t individu=0;
  for(uint8_t i=0;i<nbtask;i++){
    coord[i].indexIndividu=individu;
    individu=(individu+1)%nbindividu;
  }
}

void attribNewIndividu(uint8_t indice){
  coord[indice].indexIndividu=(coord[indice].indexIndividu + 1)%nbindividu;
}

void attribPrcdtIndividu(uint8_t indice){
  coord[indice].indexIndividu=(coord[indice].indexIndividu + (nbindividu-1)) % nbindividu;
}

void bascRealisee(uint8_t indice){
  coord[indice].realisee=1-coord[indice].realisee;
}

void Ajout(uint8_t n){
  uint8_t tableau[nbindiceday];
  for(uint8_t i=0;i<nbindiceday-1;i++){
    tableau[i]=Indice[i];
  }
  tableau[nbindiceday-1]=n;
  delete[] Indice;
  Indice=new uint8_t[nbindiceday];
  for(uint8_t i=0;i<nbindiceday;i++){
    Indice[i]=tableau[i];
  }
}

void initIndice(){
  nbindiceday=0;
  for (int n=0;n<nbtask;n++){
      if(task[coord[n].indexTask].bDay & maskDay[IntDay(rtc.getDOWStr())]){
        nbindiceday++;
        Ajout(n);
      }
  }
}

void AfficheTest(){
  for (int i=0;i<7;i++){
    Serial.print(jours[i]);Serial.println(" :");
    for (int n=0;n<nbtask;n++){
      if((task[coord[n].indexTask].bDay & maskDay[i]) == maskDay[i]){
        Serial.print("\tTask name : "); Serial.print(task[coord[n].indexTask].cName);
        Serial.print("          ");
        Serial.print("\tTask indiv : ");Serial.println(individus[coord[n].indexIndividu].cName);
        attribNewIndividu(n);
      }
    }
  }
}

void Defiler(uint8_t taille){     // Fonction permettant de faire défiler le texte si celui-ci dépasse 16 caractères
  uint8_t ind=0;
  char ligne[taille];
  for(uint8_t i=0;i<strlen(task[coord[Indice[indice]].indexTask].cName);i++){
      ligne[i]=task[coord[Indice[indice]].indexTask].cName[i];
  }
  ligne[strlen(task[coord[Indice[indice]].indexTask].cName)]=' ';
  ligne[strlen(task[coord[Indice[indice]].indexTask].cName)+ 1]='-';
  ligne[strlen(task[coord[Indice[indice]].indexTask].cName)+ 2]=' ';
  for(uint8_t i=(strlen(task[coord[Indice[indice]].indexTask].cName)+3);i<taille;i++){
    ligne[i]=individus[coord[Indice[indice]].indexIndividu].cName[i-(strlen(task[coord[Indice[indice]].indexTask].cName)+3)];
  }

  Serial.println(ligne);
  
  for(uint8_t i=0;i< (taille%16 + 1);i++){
    lcd.setCursor(0,1);
    lcd.print("                ");
    lcd.setCursor(0,1);
    for (uint8_t j=ind;j<16+ind;j++){
      lcd.print(ligne[j]);
    }
    delay(200);
    ind++;
    if (etatboutonScroll!=memoireboutonScroll && etatboutonScroll==LOW){
    indice=(indice+1)%nbindiceday;
    flagaff = false;
    return;
  }
  memoireboutonScroll=etatboutonScroll;
  }
  delay(100);
  lcd.setCursor(0,1);
  lcd.print(ligne);
}

void AfficheDone(){
  uint8_t taille = strlen(FrDay(rtc.getDOWStr())) + 3;
  if(coord[Indice[indice]].realisee == true){
    lcd.setCursor(taille,0);
    lcd.print("Done");
  }
  else{
    lcd.setCursor(taille,0);
    lcd.print("     ");
  }
}

void AfficheTask(){
  if(flagaff==false)
  {
    uint8_t taille=strlen(task[coord[Indice[indice]].indexTask].cName)+3+strlen(individus[coord[Indice[indice]].indexIndividu].cName);
    if(taille>16){
      Defiler(taille);
    }
    else{
      lcd.setCursor(0,1);
       lcd.print("                ");
      lcd.setCursor(0,1);
      lcd.print(task[coord[Indice[indice]].indexTask].cName);
      lcd.print(" - ");
      if(coord[Indice[indice]].realisee==true){
        lcd.print(individus[(coord[Indice[indice]].indexIndividu + (nbindividu-1)) % nbindividu].cName);
      }
      else{
        lcd.print(individus[coord[Indice[indice]].indexIndividu].cName);
      }
    }
    flagaff=true;
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(boutonScroll,INPUT_PULLUP);
  pinMode(boutonTask,INPUT_PULLUP);
  rtc.halt(false);
  rtc.writeProtect(false);
  
  rtc.setDOW(SUNDAY);
  rtc.setTime(20, 10, 00);    //// Set the time to 12:00:00 (24hr format)
  rtc.setDate(3, 23, 2021);   // Set the date to August 6th, 2010*/
  
  initCoord();
  affectationIndividu();
  
  lcd.begin(16, 2);
  analogWrite(8,15);

  Serial.println((task[coord[0].indexTask].bDay & maskDay[IntDay(rtc.getDOWStr())]) == maskDay[IntDay(rtc.getDOWStr())]);
}

void loop() {

for(int i=0;i<nbindiceday;i++ ){
  Serial.print(Indice[i]);
  Serial.print(", ");
}
Serial.println();

  
  // Réinitialisation le jour suivant
  if(memoireday!=FrDay(rtc.getDOWStr())){
    for (int i=0;i<nbtask;i++){
      if(coord[i].realisee==true){
        coord[i].realisee=false;
      }
    }
    delete [] Indice;
  }
  memoireday=FrDay(rtc.getDOWStr());

  // Initialisation liste Indice

  initIndice();

  // Affichage du jour
  lcd.setCursor(0,0);
  lcd.print(FrDay(rtc.getDOWStr()));
  lcd.print(" : ");
  
  /*
  if(flagaff==false){
    AfficheTest();
  }
  */
  // Affichage de la tâche 
  AfficheDone();
  AfficheTask();

  // Partie bouton
  int etatboutonScroll = digitalRead(boutonScroll);
  int etatboutonTask = digitalRead(boutonTask);

  if (etatboutonScroll!=memoireboutonScroll && etatboutonScroll==LOW){
    indice=(indice+1)%nbindiceday;
    flagaff = false;
  }
  memoireboutonScroll=etatboutonScroll;

   if (etatboutonTask!=memoireboutonTask && etatboutonTask==LOW)
  {
    if(coord[Indice[indice]].realisee == false){
      bascRealisee(Indice[indice]);
      attribNewIndividu(Indice[indice]);
    }
    else{
      bascRealisee(Indice[indice]);
      attribPrcdtIndividu(Indice[indice]);
    }
  }

  memoireboutonTask=etatboutonTask;

}

J'ai également supprimer le tri qui n'était au final pas si utile que ça :slight_smile:

Mettez dimanche en premier dans l’enum (avec comme valeur 1, lundi 2, mardi 4,...) et aussi a liste de jours comme propose précédemment

Je viens d'essayer mais ça a dérégler tous mes jours :cold_sweat:

J'avais pris en compte ce décalage, pour le test permettant de savoir si telle tâche est dans tel jour j'utilise ma fonction IntDay (que j'ai également réécrite pour ce test). Elle renvoie 0 si rtc.getDOWstr() renvoie Monday etc...

Ce que j'ai modifié :

int IntDay(String DAY){
  if(DAY=="Monday"){return 1;}
  if(DAY=="Tueday"){return 2;}
  if(DAY=="Wednesday"){return 3;}
  if(DAY=="Thursday"){return 4;}
  if(DAY=="Friday"){return 5;}
  if(DAY=="Saturday"){return 6;}
  if(DAY=="Sunday"){return 0;}
}
enum t_jour : uint8_t {Dimanche = 1, Lundi = 2, Mardi = 4, Mercredi = 8, Jeudi = 16, Vendredi = 32, Samedi = 64};
const char* jours[7] = {"Dimanche","Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
uint8_t maskDay[7]={0b01000000, 0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000};

EDIT : J'ai testé en supprimant Lundi de l'initialisation des tâches qui apparaissaient Mardi et ça fonctionne (enfin :cold_sweat: ), les tâches n'apparaissent plus. Cependant les tâches associées à mardi n'apparaissent toujours pas. Il doit donc y avoir un problème avec le mask de Mardi (0b00000010) ou bien son initialisation en tant que t_jour (Mardi = 2).
Ca semble pourtant bon...

J'ai réessayé en hexa :

uint8_t maskDay[7]={0x01,0x02,0x04,0x08,0x10,0x20,0x40};

struct t_task{
  const char* cName;
  const uint8_t bDay;
}task[]={
  {"Laver Vaisselle", 0x55},
  {"Balais",0x20},
  {"Serpillere",0x20},
  {"Toilette",0x20},
  {"Tapis",0x40},
  {"Jeter Poubelles", 0x54},
  {"Sortir Poubelles",0x02},
  {"Rentrer Poubelles",0x04},
  {"Douche",0x20},
  {"Bar", 0x55e},
  {"Plan Travail",0x55},
  {"Ranger Vaisselle", 0x55},
  {"Table", 0x54},
  {"Table Basse", 0x7F},
  {"Lavabo",0x20},
  {"Tele",0x40}
};

et toujours le même problème.

Pourtant dans le moniteur série :
Serial.println(0x55 & 0x02) retourne bien 0;

Le problème viendrait de cette fonction ?:

void initIndice(){
  nbindiceday=0;
  for (int n=0;n<nbtask;n++){
      if(task[coord[n].indexTask].bDay & maskDay[IntDay(rtc.getDOWStr())]){
        nbindiceday++;
        Ajout(n);
      }
  }
}
void Ajout(uint8_t n){
  uint8_t tableau[nbindiceday];
  for(uint8_t i=0;i<nbindiceday-1;i++){
    tableau[i]=Indice[i];
  }
  tableau[nbindiceday-1]=n;
  delete[] Indice;
  Indice=new uint8_t[nbindiceday];
  for(uint8_t i=0;i<nbindiceday;i++){
    Indice[i]=tableau[i];
  }
}

Y-a-t'il un problème avec les types ?

williamlls:
De ce que j'ai compris, les structures sont des classes simples dont les données membres sont publiques, c'est bien ça ?

En C++, la seule différence entre une struct et une class est que:

  • dans une struct, les membres sont par défaut publics,
  • dans une class, les membres sont par défaut privés.

Bien entendu, dans les 2 cas, on peut modifier ça avec les mots clés public:  private: et protected:

Pourquoi faire cela ?

uint8_t maskDay[7]={0b01000000, 0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000};

alors que vous avez l'enum qui contient déjà les bons masques.

déclarez la structure comme ceci avec un uint8_t pour les jours sélectionnés :

 struct t_task {
  const char* taskName;
  const uint8_t taskDays;
} tasks[]={
  {"Laver Vaisselle", Lundi | Mercredi | Vendredi | Dimanche},
  {"Balais", Samedi},
  ...
};
const uint8_t nbTasks = sizeof tasks / sizeof tasks[0];

et pour trouver par exemple toutes les tâches se passant un Lundi vous faites

for (uint8_t t = 0; t < nbTasks; t++) {
  if (tasks[t].taskDays & Lundi) {
    .... // Lundi est un jour actif pour cette tâche
  }
} (

Concernant l'horloge RTC, je vous conseille de remplacer la DS1302 (qui va dériver très très vite) par une DS3231 et d'utiliser la bibliothèque RTClib.h

Pour le moment avec votre DS1302, je ne sais pas exactement quelle bibliothèque vous avez retenu.

Si vous demandez à votre horloge quel est le jour en cours, il se peut qu'elle retourne les valeurs suivantes:

    Sunday    = 1,
    Monday    = 2,
    Tuesday   = 3,
    Wednesday = 4,
    Thursday  = 5,
    Friday    = 6,
    Saturday  = 7

(msparks ) donc il faut soustraire 1 pour obtenir l'indice dans les tableaux de noms de jour, si vous mettez bien Dimanche en premier dans le tableau.

D'autres bibliothèques (Rinky-Dink) vont prendre la notation suivante

MONDAY: 1
TUESDAY: 2
WEDNESDAY: 3
THURSDAY: 4
FRIDAY: 5
SATURDAY: 6
SUNDAY: 7

donc dans ce cas il faut prendre le N° du jour -1 et mettre Lundi en premier ou alors prendre un modulo 7 et vous aurez dimanche à 0 et les autres restent identiques

Si vous prenez une DS3231,la RTClib retourne dimanche en premier à 0 donc il n'y a pas de manipulation à effectuer.

Les fonctions qui analysent des String pour vous retourner le nom en français sont inutiles dans ce cas, prenez juste le N° du jour de la semaine dans le temps lu par la bibliothèque et (avec éventuellement la petite manipulation sur l'indice), vous aurez le nom du jours directement dans le tableau jours[numJour]; et si vous voulez utiliser l'enum, comme dit précédemment il faut faire par exemple jours[__builtin_ctz(Lundi)]pour obtenir la chaîne de caractère "Lundi"

et si vous voulez l'enum à partir du numéro du jour, vous faites simplement t_jour jourCourant = (t_jour) (1 << numJour);ce qui va vous donner la bonne puissance de 2