Clock

Définition Utilisation Exemple Côté technique
 

Déclaration d'un objet statique, utilisation de onSelectFunction Voir Clock: Exemple-801-Clock-Statique-onTimeFunction.ino
Déclaration d'un objet dynamique globale, utilisation de onSelectFunction Voir Clock: Exemple-802-Clock-Dynamique-onTimeFunction.ino
Déclaration d'un objet dynamique dans le setup(), utilisation de onSelectFunction Voir Clock: Exemple-803-Clock-Dynamique-setup-onTimeFunction.ino
Déclaration d'un objet statique, nouvelle classe Voir Clock: Exemple-804-Clock-Statique-Classe.ino
Déclaration d'un objet dynamique globale, nouvelle classe Voir Clock: Exemple-805-Clock-Dynamique-Classe.ino
Déclaration d'un objet dynamique dans le setup(), nouvelle classe Voir Clock: Exemple-806-Clock-Dynamique-setup-Classe.ino
Déclaration d'un objet dynamique dans le setup() sans pointeur, nouvelle classe Voir Clock: Exemple-807-Clock-SansPointeur-Classe.ino
Pour se détendre, utilisation de Timer et PushZone Voir Clock: Exemple-808-Clock-Sapin_de_Noel.ino

 


 

Dans les exemples qui suivent un métronome change la couleur de l'écran toutes les deux scondes. Il y a plusieurs façons de le faire, on peut la plupart du temps n'utiliser que la première forme. D'autres sont intéressantes si on a plusieurs métronomes identiques, mais dans l'exemple simplifié, comme c'est la mise en place qui me préoccupe, les programmes sont réduits, et l'intérêt de telles déclarations n'apparaît plus.

Les 7 premiers exemples montrent 7 façons (parfois assez semblables) de déclarer un métronome. De la même façon on peut déclarer tous les objets (horloges, mais aussi boutons...). Ces 7 exemples ne seront pas repris systématiquement, sauf pour le premier bouton.

Le huitième exemple est une application sympathique.

Premier exemple: déclaration statique

C'est la façon la plus simple d'utiliser un métronome. L'instance est statique.

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-801-Clock-Statique-onTimeFunction\Exemple-801-Clock-Statique-onTimeFunction.ino (dans votre fichier téléchargé):

// Mise en place d'un métronome. Toutes les 2s, il change la couleur du fond
// de l'écran

// Version 1:
// - L'horloge a une définition statique
// - Utilise onTimeFunction pour exécuter l'action à faire 

#include <PecheuxGraph.h> // Appel de la bibliothèque 

 
// Déclaration statique de l'instance, doit se faire en dehors du setup
// Si on la définissait dans le setup elle serait détruite au sortir du setup et
// en pariculier lorsque l'on en a besoin (dans le loop).
Clock metronome(2000); // Déclaration  d'un métronome, action toutes les 2 secondes


// Déclaration d'une fonction qui fera ce qu'il faut faire toutes les fin de comptage
// Peut se mettre avant ou après la déclaration de la variable
// Cette fonction ne doit pas avoir de paramètres et ne doit rien retourner
// Le nom peut être quelconque
void onTimeAction(void)
{
  clrscr(RANDOM_COLOR); // Action à faire chaque seconde
}


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()

  // Association de la fonction qui va faire le travail avec le métronome
  // Attention, il y a un caractère "&" avant le nom de la fonction.
  // Cette ligne veut dire: metronome a une propriété onTimeFunction et on va
  // affecter cette propriété avec l'adresse (présence du "&") de onTimeAction
  metronome.onTimeFunction=&onTimeAction; // Fonction à appeler toutes les secondes
}


void loop() 
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop
}

Deuxième exemple: déclaration dynamique avant le setup.

Quand on déclare l'instance, on obtient un pointeur sur metronome. les pointeurs sont utiles pour parcourir différents objets. En pricipe, cela a peu d'intérêt. Si on voulait accéder à une liste d'hologe, on peut passer par la liste du gestionnaire.

La déclaration est faite ici avant le setup

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-802-Clock-Dynamique-onTimeFunction\Exemple-802-Clock-Dynamique-onTimeFunction.ino (dans votre fichier téléchargé):

// Mise en place d'un métronome. Toutes les 2s, il change la couleur du fond
// de l'écran

// Version 2:
// - L'horloge a une définition dynamique avant le setup
// - Utilise onTimeFunction pour exécuter l'action à faire 

#include <PecheuxGraph.h> // Appel de la bibliothèque 

 
// Déclaration dynamique de l'instance, peut se faire en dehors du setup
// Dans ce cas horloge est accessible partout
Clock *horloge = new Clock(2000); // Déclaration  d'un métronome, action toutes les 2 secondes


// Déclaration d'une fonction qui fera ce qu'il faut faire toutes les fin de comptage
// Peut se mettre avant ou après la déclaration de l'instance horloge
// Cette fonction ne doit pas avoir de paramètres et ne doit rien retourner
// Le nom peut être quelconque
void onTimeAction(void)
{
  clrscr(RANDOM_COLOR); // Action à faire chaque seconde
}


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()

  // Association de la fonction qui va faire le travail avec le métronome
  // Attention, il y a un caractère "&" avant le nom de la fonction.
  // Cette ligne veut dire: metronome a une propriété onTimeFunction et on va
  // affecter cette propriété avec l'adresse (présence du "&") de onTimeAction
  horloge->onTimeFunction=&onTimeAction; // Fonction à appeler toutes les secondes
}


void loop() 
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop
}

Troisième exemple: déclaration dynamique dans le setup.

C'est pratiquement la même chose que dans l'exemple précédent, mais l'instance est déclarée dans le setup. Dans ce cas, l'instance est dans la pile et est accessible tout le temps, mais seul le pointeur est détruit au sortir du setup. Ou pourrait aussi sur le même principe déclarer l'instance dans une fonction.

Même si le pointeur est détruit au sortir de la fonction, pendant qu'il exixte, on peut accéder à l'objet. Cela permet en particuler d'utiliser une boucle pour définir plusieurs objets semblables dans le style:

Clock *horloge;
for (byte numero=0; numero<10; numero++)
{
  horloge = new Clock(random(100)*100+1000*numero); // Déclaration  d'un métronome, action n'importe quand
  horloge->onTimeFunction=&onTimeAction; // Fonction à appeler
}
Dans cet exemple, il va y avoir 10 métronomes qui battent avec des périodes différentses. Au bout du compte, la fonction onTimeAction() va être appellé pseudoaléatoirement.

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-803-Clock-Dynamique-setup-onTimeFunction\Exemple-803-Clock-Dynamique-setup-onTimeFunction.ino (dans votre fichier téléchargé):

// Version 3:
// - L'horloge a une définition dynamique dans le setup()
// - Utilise onTimeFunction pour exécuter l'action à faire

#include <PecheuxGraph.h> // Appel de la bibliothèque 


// Déclaration d'une fonction qui fera ce qu'il faut faire toutes les fin de comptage
// Cette fonction ne doit pas avoir de paramètres et ne doit rien retourner
// Le nom peut être quelconque
void onTimeAction(void)
{
  clrscr(RANDOM_COLOR); // Action à faire chaque seconde
}


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()

  // Déclaration dynamique de l'instance, faite dans une fonction
  // Dans ce cas l'instance est accessible partout, mais le pointeur
  // horloge sera détruit en sortant de la fonction (ici du setup())
  Clock *horloge = new Clock(2000); // Déclaration  d'un métronome, action toutes les 2 secondes
  // Association de la fonction qui va faire le travail avec le métronome
  // Attention, il y a un caractère "&" avant le nom de la fonction.
  // Cette ligne veut dire: metronome a une propriété onTimeFunction et on va
  // affecter cette propriété avec l'adresse (présence du "&") de onTimeAction
  horloge->onTimeFunction = &onTimeAction; // Fonction à appeler toutes les secondes
}


void loop()
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans le loop
}

Quatrième exemple: Surcharge de onTime, déclaration statique.

Si on a besoin de plusieurs horloges ayant des comportements identiques, on a vu qu'on peut écrire une fonction externe pour gérer la fin du comptage. Pour chaque horloge, il faudra alors lui associer cette fonction externe. En définissant une classe fille de Clock et en surchargeant onTime(), on aura plus qu'a déclarer l'instance, la fonction étant dedans. C'est un peu plus lourd, mais le code peut être plus clair.

Notez que l'on n'a pas besoin d'accéder au métronome un fois défini, le nom de la variable ne nous sert à rien

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-804-Clock-Statique-Classe\Exemple-804-Clock-Statique-Classe.ino (dans votre fichier téléchargé):

// Mise en place d'un métronome. Toutes les 2s, il change la couleur du fond
// de l'écran

// Version 4:
// - On définir une classe Metronome, dérivée de Clock, avec le bon comportement
// - Metronome a une définition statique

#include <PecheuxGraph.h> // Appel de la bibliothèque 


class Metronome: public Clock // Nouvelle classe pour redéfinir onTime 
{
 public: 
  Metronome(unsigned long duree):Clock(duree){} // Constructeur qui copie la classe mère
  virtual void onTime(void) // Nouveau comportement
  {  
    clrscr(RANDOM_COLOR); // Action à faire chaque seconde 
  }
}; // Ne pas oublier le ; à la fin de la déclaration d'une classe


// Déclaration statique de l'instance, doit se faire en dehors du setup
// Si on la définissait dans le setup elle serait détruite au sortir du setup et
// en pariculier lorsque l'on en a besoin (dans le loop).
Metronome metronome(2000); // Déclaration  d'un métronome, action toutes les 2 secondes


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()
}


void loop() 
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans loop()
}

Cinquième exemple: Surcharge de onTime, déclaration dynamique.

Si l'on crée une nouvelle classe, il est aussi possible de définir des insances sur les pointeurs.

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-805-Clock-Dynamique-Classe\Exemple-805-Clock-Dynamique-Classe.ino (dans votre fichier téléchargé):

// Mise en place d'un métronome. Toutes les 2s, il change la couleur du fond
// de l'écran

// Version 5:
// - On définir une classe Metronome, dérivée de Clock, avec le bon comportement
// - Metronome a une définition dynamique

#include <PecheuxGraph.h> // Appel de la bibliothèque 


class Metronome: public Clock // Nouvelle classe pour redéfinir onTime
{
  public:
    Metronome(unsigned long duree): Clock(duree) {} // Constructeur qui copie la classe mère
    virtual void onTime(void) // Nouveau comportement
    {
      clrscr(RANDOM_COLOR); // Action à faire chaque seconde
    }
}; // Ne pas oublier le ; à la fin de la déclaration d'une classe


// Déclaration dynamique de l'instance, peut se faire en dehors du setup
// Dans ce cas metronome est accessible partout
Metronome *metronome = new Metronome(2000); // Déclaration  d'un métronome, action toutes les 2 secondes


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()
}


void loop()
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans loop()
}

Sixième exemple: Surcharge de onTime, déclaration dynamique dans une fonction.

Comme cela a été fait plus haut, que l'on dérive une nouvelle classe ou pas, on peut créer l'instance metronome dans une fonction. Comme tout à l'heure, l'instance existe partout, mais le pointeur metronome n'est accessible que dans la fonction qui l'a définie.

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-806-Clock-Dynamique-setup-Classe\Exemple-806-Clock-Dynamique-setup-Classe.ino (dans votre fichier téléchargé):

// Mise en place d'un métronome. Toutes les 2s, il change la couleur du fond
// de l'écran

// Version 6:
// - On définir une classe Metronome, dérivée de Clock, avec le bon comportement
// - Metronome a une définition dynamique dans une fonction

#include ;lt&PecheuxGraph.h> // Appel de la bibliothèque 


class Metronome: public Clock // Nouvelle classe pour redéfinir onTime
{
  public:
    Metronome(unsigned long duree): Clock(duree) {} // Constructeur qui copie la classe mère
    virtual void onTime(void) // Nouveau comportement
    {
      clrscr(RANDOM_COLOR); // Action à faire chaque seconde
    }
}; // Ne pas oublier le ; à la fin de la déclaration d'une classe


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()
  
  // Déclaration dynamique de l'instance, peut se faire dans une fonction
  // Dans ce cas l'instance est accessible partout, mais le pointeur
  // horloge sera détruit en sortant de la fonction (ici du setup())
  Metronome *metronome = new Metronome(2000); // Déclaration  d'un métronome, action toutes les 2 secondes
}


void loop()
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans loop()
}

Septième exemple: Surcharge de onTime, déclaration dynamique dans une fonction, sans pointeur.

Dans la dernière version, on voit que l'on n'a pas besoin du pointeur. Dans ce cas, ce n'est pas la peine d'en avoir un.

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-807-Clock-SansPointeur-Classe\Exemple-807-Clock-SansPointeur-Classe.ino (dans votre fichier téléchargé):

// Mise en place d'un métronome. Toutes les 2s, il change la couleur du fond
// de l'écran

// Version 7:
// - On définir une classe Metronome, dérivée de Clock, avec le bon comportement
// - Metronome a une définition dynamique sans pointeur

#include ;lt&PecheuxGraph.h> // Appel de la bibliothèque 


class Metronome: public Clock // Nouvelle classe pour redéfinir onTime
{
  public:
    Metronome(unsigned long duree): Clock(duree) {} // Constructeur qui copie la classe mère
    virtual void onTime(void) // Nouveau comportement
    {
      clrscr(RANDOM_COLOR); // Action à faire chaque seconde
    }
}; // Ne pas oublier le ; à la fin de la déclaration d'une classe


void setup()
{
  setGraphMode(PAYSAGE); // Pour pouvoir utiliser clrscr()
  
  // Déclaration dynamique de l'instance, mais on n'a pas besoin du pointeur
  // On peut donc créer une instance sans avoir une référence. 
  new Metronome(2000); // Déclaration  d'un métronome, action toutes les 2 secondes
}


void loop()
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans loop()
}

Huitième exemple: Le sapin de Noël.

35 métronomes avec un Uno, et une boucle quasi obligatoire our tout initialiser, en dérivant une nouvelle classe. C'est plus une démonstration. On peut mettre 250 métronomes avec un Mega

PecheuxGraph.zip\PecheuxGraph\examples\Documentation\Exemple-808-Clock-Sapin_de_Noel\Exemple-808-Clock-Sapin_de_Noel.ino (dans votre fichier téléchargé):

// Ce programme dessine un sapin de Noël puis 35 métronomes vont faire
// changer de couleur les 35 boules de Noël à des instants légèrement
// différents (entre 2 et 2,1 seconde). Au début, les boules changent de
// couleur presque en même temps, puis à la longue, elles vont devenir
// indépendantes
// Avec un Mega, on peut mettre 250 métronomes

#include <PecheuxGraph.h>

// Comme le comportement de chaque métronome est légèrement différent, a
// savoir que la boule associée est positionnée différemment pour chacun
// d'eux, il faut que chaque métronome mémorise ces coordonnes. Dériver
// une nouvelle classe est une bonne solution
const word couleurs[]={RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW};
class Boule: public Clock
{
  public:
    Boule(int x, int y, unsigned long duree): Clock(duree)
    {
      this->x = x; this->y = y; // Dans ce constructeur, on rajoue l'initialisation des coordonnées
    }
    int x; int y; // Coordonnée de la boule associée
    virtual void onTime(void) // Nouveau comportement
    {
      fillRect(x, y, x+2, y+2, couleurs[random(6)]); //On change de couleur la boule associée (5 chances sur 6!)
    }
};


void setup()
{
  long x, y; // Coordonnés d'un point
  setGraphMode(PORTRAIT);

  // Le sapin
  if (bpxDraw("TOOLS/NOEL.BPX", 0, 0)) // Photo d'un sapin
  { // Pas de carte ou pas de fichier, on va tout dessiner à la main
    line(0, 240, 134, 223, BISQUE); lineTo(239,258); fill(134,250, BISQUE); // Sol
    fill(0,0,LIGHT_YELLOW); // Mur
    line(121, 38, 50, 241, DARK_GREEN); lineTo(177, 241); lineTo(121, 38); // Contour du sapin
    fill(121, 50, DARK_GREEN); fill(121, 239, DARK_GREEN); //Vert du sapin
    fillRect(110,240,132,290,DARK_RED); // Tronc
  }

  // Déclaration des 40 métronomes. Comme il y en a beaucoup, une boucle
  // est bienvenue. On est donc obligé d'avoir une déclaration dynamique. On
  // n'a pas besoin du pointeur créé, on n'en utilise pas
  for (byte nombre = 0; nombre < 35; nombre++) // Au dela de 40 avec un Uno, la pile déborde et le programme plante
  {
    do
    {
      x = random(178); // Coordonnées au hasard, mais pour l'instant cela risque de dépasser du sapin
      y = random(242); 
    }
    // Pour la condition pas trop à gauche, le sapin étant vaguement
    // triangulaire, il ne faut pas que les points soient à gauche de la
    // droite passant par (121,38) et (50,241). Il faut calculer l'équation
    // de la droite du type ax+by+c; si c'est nul, on est sur la droite, si
    // c'est négatif, on est dans un des deux demi-plan, si c'est positif on
    // est dans l'autre demi-plan. Un essai nous dira si on a pris le bon.
    // le point (x,y) est sur la droite passant par (x1,y1) et (x2,y2) si
    //   x - x1      x1 - x2
    //   ------  =   -------
    //   y - y1      y1 - y2
    // L'équation de la droite recherchée est:
    // (x - x1)*(y1 - y2) - (y - y1)*(x1 - x2) = 0
    // on testera si le membre de droite est nul (on est sur la limite du sapin)
    //                                       positif (on est d'un côté)
    //                                       négatif (on est de l'autre côté)
    while ((203*x+71*y-27261<=0) // Pas trop à gauche
           || (203*x-56*y-22425>=0)); // Pas trop à droite
    new Boule(x-1, y-1, 500 + nombre); // (x,y) étant dans le sapin, on créé le métronome
  }
}

void loop()
{
  scanEvent(); // Gestion des boutons et des horloges, le plus souvent seul dans loop()
}

 

Voir aussi:
- scanEvent(); Moteur de la gestion des évènements
- Timer; Temporisateur (une action une seule fois)