Abonnement aux commentaires

S'abonner pour recevoir les commentaires suivants par email

まこと の ブログ

MaKoTo no burogu — Journal de bord…

Aller au contenu | Aller au menu | Aller à la recherche

WebRadioRéveilWifi -4-

Suite de l'étude précédente :

Je vais (enfin !!) reprendre la conception de mon WebRadioReveilWifi, après que tant de temps ait passé…
Il est désormais fonctionnel et me réveille correctement tous les matins, et c'est dans une suite de plusieurs billets que je vais détailler la réalisation étape par étape.


L'horloge :

Cette maquette m'a pas mal servi à apprendre Arduino et voir où les expérimentations me menaient, afin de bien dimensionner la suite.
C'est ainsi que j'ai pu router un circuit imprimé, puis graver percer et souder la plaque…
Cependant même si on croit avoir toujours tout prévu, j'ai tout de même dû modifier certaines choses sur mon circuit, une erreur fâcheuse et des modifications de dernières minutes.
C'est donc le circuit final réalisé sur Kicad que je vais livrer ici (en annexe du billet), il ne correspondra pas aux photos, sur lesquelles apparaissent donc les modifications et bricolage de rattrapages.

  • Le Schéma structurel de la carte principale :

horlogeStructurel.png

  • Le circuit de la carte principale :

horloge.png

horlogeSerigraphie.png horlogeCuivreDessous.png horlogeCuivreDessus.png

  • Liste des composants:
Nom                 Type et valeur

Shield1             Arduino Pro Mini 5V
P1, P6              Pin header x3
P2                  Pin header x6
P5                  Pin header x2
P3                  Pin header HE10-10
P4                  Bornier 2 vis
D1, D2              Led Verte
D3, D4              Led Rouge
D5                  Photodiode LSL100 ou Photorésistance 5516
R6, R7              Résistances  1kΩ
R11                 Résistances  2,2kΩ
R12 à R18           Résistances  39Ω
R19                 Résistances  150Ω
R20 à R26           Résistances  39Ω
R27                 Résistances  150Ω
R28 à R34           Résistances  39Ω
R35                 Résistances  150Ω
R36 à R42           Résistances  39Ω
R43                 Résistances  150Ω
Afficheur1, 2, 3, 4 Afficheur 7 segments SA10-21GWA-Kingbright 25,4 mm Vert
Q1, Q2, Q3, Q4, Q5  BC547
C7, C8, C9,C10      Condensateur 100nF
U1, U2, U3, U4      74HC595


  • Le Schéma structurel de la carte des boutons :

boutons_horlogeStructurel.png

  • Le circuit de la carte des boutons :

boutons_horloge.png
boutons_horlogeSerigraphie.png boutons_horlogeCuivreDessous.png

  • Liste des composants:
Nom                             Type et valeur

C1, C2, C3, C4, C5, C6          Condensateur 100nF
SW1, SW2, SW3, SW4, SW5, SW6    Petit bouton poussoir
R1, R2, R3, R4, R5, R6          Résistances  10kΩ
P1                              Pin header HE10-10


Une petit video !

dsc03253.jpg dsc03257.jpg

  • Voici les cartes et les composants parés pour la soudure.

dsc03266.jpg dsc03271.jpg

  • Mais avant, car réalisé en simple face, je n'ai pu faire autrement que de passer quelques liaisons sur l'autre face, et donc ici de devoir souder quelques fils en lieu et place.

dsc03268.jpg dsc03273.jpg

  • Pour plier les pattes des résistances, je me suis aidé d'un plioir imprimé3D… Étant donné le grand nombre de résistances, c'était pas du luxe !

dsc03275.jpg dsc03278.jpg

  • Je pense que la suite se passe de trop de commentaire, avec la soudure progressive les composants, des plus maigres aux plus épais.

dsc03276.jpg dsc03277.jpg dsc03279.jpg dsc03280.jpg

dsc02385b.jpg

  • Le module RTC (Real Time Clock) à base de DS3231 peut se trouver tout fait, mais ici je disposait seulement du composant, voulant rester compatible avec le concept du module enfichable, j'ai tout simplement réalisé une petite carte qui fait le même job, avec sa pile de sauvegarde !

dsc03282.jpg dsc03283.jpg

ChronodotStructurel.png Chronodot.png ChronodotSerigraphie.png ChronodotCuivreDessus.png

  • Liste des composants:
Nom      Type et valeur

C6       Condensateur 100nF
R9, R10  Résistances  10kΩ
U5       DS3231N
BT1      Support de pile Bouton 3V (CR2032)
P1       Pin header x6
  • Voilà donc tout est prêt, avec la carte principale qui accueillera (en haut) les 4 afficheurs 7 segments, les quatre 74HC595, (à droite) l'Arduino, (à gauche) la plaquette de boutons reliée au centre de la carte principale par une nappe de connecteur, (en bas) le capteur de mouvement (PIR) et le module RTC.

dsc03285.jpg

L'ampli audio :

  • Dans l'épisode précédent, j'avais donc câblé un petit ampli à base de LM386 sur une plaquette labo afin d'en valider le fonctionnement, puis j'en ai dessiné un circuit sur Kicad qui a été réalisé en simple face et que l'on va voir ci-après.

Cependant, comme pour l'horloge, j'ai un moment perdu de vue mes desiderata, et en rajoutant une source audio, je me suis plus tard rendu compte que j'avais oublié une partie du circuit pour le mélange des signaux entrants.
Et ce n'est pas tout… En intégrant l'ampli dans le boîtier du WebRadioRéveil que nous verrons dans un autre billet, j'ai vite compris que j'allais devoir retirer un certains nombre de connecteurs. Le circuit final réalisé sur Kicad (en annexe du billet), contient donc toutes les modifications et ne correspondra donc pas tout à fait aux photos.

  • Le schéma structurel de l'ampli :

AmpliAudioStructurel.png

  • Le circuit de l'ampli :

AmpliAudio.png
AmpliAudioSerigraphie.png AmpliAudioCuivreDessous.png

  • Liste des composants:
Nom                   Type et valeur

C13, C14, C15, C16    Condensateur électrochimique polarisé 47µF 16V
C2, C5, C8, C11       Condensateur électrochimique polarisé 10µF 16V
C3, C9                Condensateur électrochimique polarisé 470µF 16V
C4, C10               Condensateur 33nF
C6, C12               Condensateur 100nF
C1, C7                Condensateur 1µF
R4, R5, R6, R7        Résistances  2,2kΩ
R8, R9                Résistance  100Ω
R1, R3                Résistances  1,2kΩ
R2                    Résistances  1,5kΩ
RV1, RV2              Potentiomètre  Double 10kΩ
U1, U2                LM386N-3
D1                    Led Jaune 3 mm
SP1, SP2              Petit Haut Parleur
  • Une petit video !

dsc03262.jpg dsc03264.jpg

  • Tous les composants parés pour la soudure !

dsc03287.jpg
On verra donc plus tard que ce sont les deux jacks audio, le jack alim et le bornier que j'ai dû retirer. Et de rajouter une petite carte intégrant le mélangeur audio.

Le code :

  • Une fois le hardware terminé, il reste à revoir et améliorer le code commencé la dernière fois.

dsc03289.jpg
Tout le système assemblé proprement sur table pour coder sereinement.
À gauche de Raspberry Pi et sa carte de boutons pour piloter manuellement la radio, au dessus l'ampli audio relié au Raspberry Pi , et donc à droite l'horloge avec son Arduino, son module RTC et sa carte de boutons.

  • Le code et les deux librairies nécessaire pour Arduino sont disponible en annexe du billet.

Ce code est à utiliser avec Arduino 1.5.5

/****** Domaine publique, youpi ! ******/
/****** Ce code est à utiliser avec Arduino 1.5.5 *****/
#include <Wire.h>       // Communication avec le RTC
#include <Tone.h>       // Sonnerie ChipTune, voir Librairie
#include "Chronodot.h"  // Fonctions du Chronodot, voir Librairie modifiée

/****************/
/* Déclarations */
/****************/
#define CHRONODOT_ADDRESS 0x68

/****** Signaux ******/
#define datapin 10   // pin 10 pour les données vers les registres à décallages 74HC595
#define clockpin 11  // pin 11 pour l'horloge qui coordonne les registres à décallages
#define latchpin 8   // pin 8 pour le déclencheur des registres à décallages

/****** Boutons poussoir ******/
#define BoutonMinutes 12    // pin 12 pour le bouton poussoir d'incrément des minutes
#define BoutonHeures 13     // pin 13 pour le bouton poussoir d'incrément des heures
#define BoutonAlarme1 6     // pin 6 pour le bouton poussoir Alarme1
#define BoutonAlarme2 2     // pin 2 pour le bouton poussoir Alarme2, alias « interruption 0 »
#define BoutonHorloge 7     // pin 7 pour le bouton poussoir Horloge
#define BoutonSupp 1        // pin TX1 pour le bouton supplémentaire
#define relais A2           // pin analogique 2 pour le pilotage du relais ON/OFF AmpliAudio
#define Radio A3            // pin analogique 3 pour le déclenchement de la radio (relié par la carte d'interface 5V -> 3V) à l'un des GPIO du Rpi

/****** LED ******/
#define LedAlarm1 4       // pin 4 pour la led de l'alarme1
#define LedAlarm2 3       // pin 3 pour la led de l'alarme2

/****** Alimentation des 7 segments en PWM ******/
#define ledPin 9          // pin 9 pour le signal PWM de cadencement des afficheurs et leds
#define photodiodepin A0  // pin A0 pour la photodiode

/****** Variables d'état ******/
int EtatBoutonMinutes = 1;  // pour stocker l'état du bouton aprés sa lecture
int EtatBoutonHeures = 1;   // idem
int EtatBoutonAlarme1 = 1;  // idem
int EtatBoutonAlarme2 = 1;  // idem
int EtatBoutonHorloge = 1;  // idem
int EtatBoutonSupp = 1;     // idem
unsigned int ValeurPhotoDiode = 0;  // pour stocker l'état de la photodiode aprés sa lecture
volatile int change = 0;    // pour mémoriser l'état de l'interruption 0

/****** Variables temporelles ******/
unsigned int heuresHorloge;    // pour stocker les heures
unsigned int heuresHorlogeINC; // pour stocker l'incrément des heures
unsigned int minutesHorloge;   // pour stocker les minutes
unsigned int minutesHorlogeINC;// pour stocker l'incrément des minutes
unsigned int secondes;  // pour stocker les secondes
unsigned int annee;     // pour stocker l'annee
unsigned int mois;      // pour stocker le mois
unsigned int jour;      // pour stocker le jour
unsigned int heuresAlarme;    // pour stocker les heures
unsigned int heuresAlarmeINC; // pour stocker l'incrément des heures
unsigned int minutesAlarme;   // pour stocker les minutes
unsigned int minutesAlarmeINC;// pour stocker l'incrément des minutes

/****** Variables d'affichage ******/ 
int dizH = 0;          // pour stocker les dizaine des heures
int unitH = 0;         // pour stocker les unités des heures
int dizM = 0;          // pour stocker les dizaine des minutes
int unitM = 0;         // pour stocker les unités des minutes
byte AfficheurUN;      // données binaire pour l'afficheur UN, situé le plus à droite
byte AfficheurDEUX;    // données binaire pour l'afficheur DEUX
byte AfficheurTROIS;   // données binaire pour l'afficheur TROIS
byte AfficheurQUATRE;  // données binaire pour l'afficheur QUATRE, situé le plus à gauche
byte dataArray[10];    // Tableau de données

/****** Référenciel librairies ******/ 
Chronodot HORLOGE;      // HORLOGE, nom choisi arbitrairement, référence à la librairie Chronodot
ChronodotAlarm1 RADIO;
ChronodotAlarm2 REVEIL;

/**** Variable de construction des sonneries *****/
Tone tone1;

#define OCTAVE_OFFSET 0
#define isdigit(n) (n >= '0' && n <= '9')

int notes[] = { 0,
NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
};

char *songA = "A-Team:d=8,o=5,b=125:4d#6,a#,2d#6,16p,g#,4a#,4d#.,p,16g,16a#,d#6,a#,f6,2d#6,16p,c#.6,16c6,16a#,g#.,2a#";
char *songB = "Hallowee:d=4,o=5,b=140:32p,8d6,8g,8g,8d6,8g,8g,8d6,8g,8d#6,8g,8d6,8g,8g,8d6,8g,8g,8d6,8g,8d#6,8g,8c#6,8f#,8f#,8c#6,8f#,8f#,8c#6,8f#,8d6,8f#,8c#6,8f#,8f#,8c#6,8f#,8f#,8c#6,8f#,8d6,8f#";
char *songC = "Muppets:d=4,o=5,b=250:c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,8a,8p,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,8e,8p,8e,g,2p,c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,a,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,d,8d,c";
char *songD = "TakeOnMe:d=4,o=4,b=160:8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5,8f#5,8e5,8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5,8a5,8a5,8a5,8e5,8p,8d5,8p,8f#5,8p,8f#5,8p,8f#5,8e5,8e5";
char *songE = "Gadget:d=16,o=5,b=50:32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,32d#,32f,32f#,32g#,a#,d#6,4d6,32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,8d#";
char *songF = "MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,4d#,8d#.";
int song = 1;   // variable pour changer de sonnerie aprés chaque utilisation de la sonnerie

/*******************/
/* Initialisations */
/*******************/
void setup ()      // Fonction d'initialisation obligatoire
{

//  Serial.begin(9600);                         // uncomment to debug
//  Serial.println("Initializing Chronodot.");  // uncomment to debug
  
  dataArray[0] = B00000011;  // Case du tableau qui contient la valeur binaire pour afficher zero sur un afficheur 7 segments
  dataArray[1] = B10011111;  // Case du tableau qui contient la valeur binaire pour afficher un sur un afficheur 7 segments
  dataArray[2] = B00100101;  // Case du tableau qui contient la valeur binaire pour afficher deux sur un afficheur 7 segments
  dataArray[3] = B00001101;  // Case du tableau qui contient la valeur binaire pour afficher trois sur un afficheur 7 segments
  dataArray[4] = B10011001;  // Case du tableau qui contient la valeur binaire pour afficher quatre sur un afficheur 7 segments
  dataArray[5] = B01001001;  // Case du tableau qui contient la valeur binaire pour afficher cinq sur un afficheur 7 segments
  dataArray[6] = B01000001;  // Case du tableau qui contient la valeur binaire pour afficher six sur un afficheur 7 segments
  dataArray[7] = B00011111;  // Case du tableau qui contient la valeur binaire pour afficher sept sur un afficheur 7 segments
  dataArray[8] = B00000001;  // Case du tableau qui contient la valeur binaire pour afficher huit sur un afficheur 7 segments 
  dataArray[9] = B00001001;  // Case du tableau qui contient la valeur binaire pour afficher neuf sur un afficheur 7 segments

  pinMode(clockpin, OUTPUT);     // pin correspondant à "clockpin" initialisée en sortie
  pinMode(datapin, OUTPUT);      // pin correspondant à "datakpin" initialisée en sortie
  pinMode(latchpin, OUTPUT);     // pin correspondant à "latchpin" initialisée en sortie
  pinMode(BoutonMinutes, INPUT); // pin correspondant à "BoutonMinutes" initialisée en entrée 
  pinMode(BoutonHeures, INPUT);  // pin correspondant à "BoutonHeures" initialisée en entrée  
  pinMode(BoutonAlarme1, INPUT); // pin correspondant à "BoutonHeures" initialisée en entrée  
  pinMode(BoutonAlarme2, INPUT); // pin correspondant à "BoutonHeures" initialisée en entrée   
  pinMode(BoutonHorloge, INPUT); // pin correspondant à "BoutonHeures" initialisée en entrée
  pinMode(BoutonSupp, INPUT);    // pin correspondant à "BoutonSupp" initialisée en entrée  
  pinMode(LedAlarm1, OUTPUT);    // pin correspondant à "LedAlarm1" initialisée en sortie
  pinMode(LedAlarm2, OUTPUT);    // pin correspondant à "LedAlarm2" initialisée en sortie 
  pinMode(relais, OUTPUT);       // pin correspondant à "relais" initialisée en sortie 
  pinMode(Radio, OUTPUT);        // pin correspondant à "Radio" initialisée en sortie 
  tone1.begin(A1);               // pin A1 pour le jack sonnerie
   
  Wire.begin();     // initialisation du chronodot, référence à la librairie wire
  HORLOGE.begin();  // initialisation du chronodot, référence à la librairie Chronodot

//************ MISE à L'heure manuelle du module RTC DS3231 ************
//  HORLOGE.adjust(DateTime(2014,12,25,10,30,12));  // années, mois, jour, heures, minutes, secondes
//  RADIO.adjust(AlarmTime1(6,30,0));
//  REVEIL.adjust(AlarmTime2(7,30));  

  attachInterrupt(0, stop2, FALLING); // attache l'interruption externe n°0 (pin2 soit bouton Alarm2) à la fonction stop2
  digitalWrite(Radio, HIGH);  // Coupe la radio au démarrage
  RADIO.Alarm1SetON();        // au démarrage, l'alarme Radio est forcée ON (en cas de coupure de courant)
  digitalWrite (LedAlarm1, HIGH);
  REVEIL.Alarm2SetON();      // au démarrage, l'alarme Réveil est forcée ON (en cas de coupure de courant)
  digitalWrite (LedAlarm2, HIGH);
}


/*************/
/* Programme */
/*************/
void loop ()      // boucle du programme !
{
  horloge ();                // appelle la fct "horloge", récupération des données temporelles
  AfficheHorloge ();         // appelle la fct "affiche", transfert des données temporelles sur les afficheurs 7 segments
  AjusteLuminosite();        // appelle la fct "AjusteLuminosite", plus il fait sombre, plus la lumière des afficheurs baisse  
  SurveilleBouton_Horloge_Heures_Minutes ();  // Pour permettre de mettre l'horloge à l'heure
//  SurveilleBouton_Supp ();
  RadioON(); // envoie d'ordre au rpi
  FaireSonnerSonnerie();
  EtatBoutonAlarme1 = digitalRead(BoutonAlarme1);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonAlarme1"
  EtatBoutonAlarme2 = digitalRead(BoutonAlarme2);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonAlarme2"  
  
 if (EtatBoutonAlarme1 == LOW)  // sinon, si bouton alarme 1 appuyé
  {
    for (int i=0; i <= 800; i++) //  faire durant 3 sec
    {
      alarme1();    
      AfficheAlarme();   // affiche l'alarme
      SurveilleBouton_Alarme1_Heures_Minutes ();  // régler l'alarme
      SurveilleBouton_Alarme1_Horloge ();
    }
  }
  
 if (EtatBoutonAlarme2 == LOW)  // sinon, si bouton alarme 2 appuyé
  {
 //   Stopper();
    for (int j=0; j <= 800; j++) //  faire durant 3 sec
    {
      alarme2();    
      AfficheAlarme();   // affiche l'alarme
      SurveilleBouton_Alarme2_Heures_Minutes ();  // régler l'alarme
      SurveilleBouton_Alarme2_Horloge ();
    }
  }  

 if(change == 1) {    // Si change = 1, stopper la sonnerie
    change = 0;
 //     Serial.print(change); //
    RADIO.Alarm1Stop();    
    REVEIL.Alarm2Stop();
    song = song + 1;  // pour une sonnerie différente la prochaine fois
    if(song == 7) {
      song = 1;
    }
 //     Serial.print(", song:"); //
 //     Serial.print(song); //
  //    Serial.println();
  }
}

/****************************************/   
/***** Les Fonctions du programme *******/   
/****************************************/   

/***** Fonction d'horloge *******/   
void horloge ()
{
  DateTime now = HORLOGE.now();  // lecture de l'heure en cours dans la puce DS3231, référence à la librairie Chronodot
  heuresHorloge = now.hour(), DEC;      // stocke l'heure en décimale dans la variable "heures" grace à la fct "hour" de la lib chronodot
  minutesHorloge = now.minute(), DEC;   // stocke les minutes en décimale dans la variable "minutes" grace à la fct "minute" de la lib chronodot
  secondes = now.second(), DEC;  // stocke les secondes en décimale dans la variable "secondes" grace à la fct "second" de la lib chronodot
  annee = now.year(), DEC;       // stocke l'année en décimale dans la variable "annee" grace à la fct "year" de la lib chronodot
  mois = now.month(), DEC;       // stocke le mois en décimale dans la variable "mois" grace à la fct "month" de la lib chronodot 
  jour = now.day(), DEC;         // stocke le jour en décimale dans la variable "jour" grace à la fct "day" de la lib chronodot
//  Serial.print(annee); //
//  Serial.print(':'); //
//  Serial.print(mois); //
//  Serial.print(':'); //
//  Serial.print(jour); //
//  Serial.print(':');   //
//  Serial.print(heures);   //décommenter pour débug
//  Serial.print(':');   //
//  Serial.print(minutes); //
//  Serial.println();  //
}

/***** Fonction d'alarme 1 *******/   
void alarme1 ()
{
  AlarmTime1 now = RADIO.now();  // lecture de l'heure en cours dans la puce DS3231, référence à la librairie Chronodot
  heuresAlarme = now.hourA1(), DEC;      // stocke l'heure en décimale dans la variable "heures" grace à la fct "hour" de la lib chronodot
  minutesAlarme = now.minuteA1(), DEC;   // stocke les minutes en décimale dans la variable "minutes" grace à la fct "minute" de la lib chronodot
 // Serial.print(heuresAlarme);   //décommenter pour débug
//  Serial.print(':');   //
 // Serial.print(minutesAlarme); //
 // Serial.println();  //
}

/***** Fonction d'alarme 2 *******/   
void alarme2 ()
{
  AlarmTime2 now = REVEIL.now();  // lecture de l'heure en cours dans la puce DS3231, référence à la librairie Chronodot
  heuresAlarme = now.hourA2(), DEC;      // stocke l'heure en décimale dans la variable "heures" grace à la fct "hour" de la lib chronodot
  minutesAlarme = now.minuteA2(), DEC;   // stocke les minutes en décimale dans la variable "minutes" grace à la fct "minute" de la lib chronodot
 // Serial.print(heuresAlarme);   //décommenter pour débug
//  Serial.print(':');   //
 // Serial.print(minutesAlarme); //
 // Serial.println();  //
}

/***** Fonction d'affichage horloge sur les 7 segments *******/  
void AfficheHorloge ()
{
  dizH = heuresHorloge / 10;   // par calcul, extrait la dizaine de "heures" et stocke le résultat dans "dizH" 
  unitH = heuresHorloge % 10;  // par calcul, extrait l'unités de "heures" et stocke le résultat dans "unitH" 
  dizM = minutesHorloge / 10;  // par calcul, extrait la dizaine de "minutes" et stocke le résultat dans "dizM"   
  unitM = minutesHorloge % 10; // par calcul, extrait l'unité de "minutes" et stocke le résultat dans "dizM" 
        
  AfficheurUN = dataArray[unitM];    // stocke la valeur binaire 7 segments de l'unité de minutes dans "AfficheurUN"
//  AfficheurUN &= ~(1<<1);
  AfficheurDEUX = dataArray[dizM];   // stocke la valeur binaire 7 segments de la dizaine de minutes dans "AfficheurDEUX"
  AfficheurTROIS = dataArray[unitH]; // stocke la valeur binaire 7 segments de l'unité d'heures dans "AfficheurTROIS"
  AfficheurQUATRE = dataArray[dizH]; // stocke la valeur binaire 7 segments de la dizaine d'heures dans "AfficheurQUATRE"
//  AfficheurQUATRE &= ~(1<<1);  
  digitalWrite(latchpin, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurUN);     // envoi l'unités minute au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurDEUX);   // envoi la dizaine minute au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurTROIS);  // envoi l'unités heure au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurQUATRE); // envoi la dizaine heure au registre à décallage  
  digitalWrite(latchpin, 0);                              // latch à l'état BAS pour arreter le transfert des données série  
}

/***** Fonction d'affichage alarmes sur les 7 segments *******/  
void AfficheAlarme ()
{
  dizH = heuresAlarme / 10;   // par calcul, extrait la dizaine de "heures" et stocke le résultat dans "dizH" 
  unitH = heuresAlarme % 10;  // par calcul, extrait l'unités de "heures" et stocke le résultat dans "unitH" 
  dizM = minutesAlarme / 10;  // par calcul, extrait la dizaine de "minutes" et stocke le résultat dans "dizM"   
  unitM = minutesAlarme % 10; // par calcul, extrait l'unité de "minutes" et stocke le résultat dans "dizM" 
        
  AfficheurUN = dataArray[unitM];    // stocke la valeur binaire 7 segments de l'unité de minutes dans "AfficheurUN"
  AfficheurDEUX = dataArray[dizM];   // stocke la valeur binaire 7 segments de la dizaine de minutes dans "AfficheurDEUX"
  AfficheurTROIS = dataArray[unitH]; // stocke la valeur binaire 7 segments de l'unité d'heures dans "AfficheurTROIS"
  AfficheurQUATRE = dataArray[dizH]; // stocke la valeur binaire 7 segments de la dizaine d'heures dans "AfficheurQUATRE"
  
  digitalWrite(latchpin, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurUN);     // envoi l'unités minute au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurDEUX);   // envoi la dizaine minute au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurTROIS);  // envoi l'unités heure au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurQUATRE); // envoi la dizaine heure au registre à décallage  
  digitalWrite(latchpin, 0);                              // latch à l'état BAS pour arreter le transfert des données série  
}


/***** Régler l'Horloge : Fonction Surveillance des BoutonHorloge, BoutonMinutes et BoutonHeures *******/    
void SurveilleBouton_Horloge_Heures_Minutes ()
{ 
  EtatBoutonHorloge = digitalRead(BoutonHorloge);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHorloge"
  EtatBoutonHeures = digitalRead(BoutonHeures);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHeures"
  EtatBoutonMinutes = digitalRead(BoutonMinutes);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonMinutes"
  if ((EtatBoutonHorloge == LOW) && (EtatBoutonHeures == LOW))  // si le bouton est appuyé
    {  
    delay(170);                  // alors, attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleHorlogeHeures ();       // et appeller la fonction "RegleHeures"
    } 
  if ((EtatBoutonHorloge == LOW) && (EtatBoutonMinutes == LOW))  // si le bouton est appuyé 
    {  
    delay(170);                    // alors,  attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleHorlogeMinutes ();        // et appeller la fonction "RegleMinutes"
    } 
}

/***** Fonction d'incrément Heures *******/ 
void RegleHorlogeHeures ()
{ 
  heuresHorlogeINC = heuresHorloge + 1;  // additionne 1 à la valeur contenue dans la variable "heures" et stocke le résultat dans la variable "heuresHorlogeINC"
  if (heuresHorlogeINC > 23)      // si la valeur de "heuresHorlogeINC" dépasse 23 (23h)
  {
    heuresHorlogeINC = 0;         // alors, et la variable "heuresHorlogeINC" à zero (minuit)
  }
//    Serial.print(heuresHorlogeINC);
//    Serial.println(); 
    HORLOGE.adjust(DateTime(annee,mois,jour,heuresHorlogeINC,minutesHorloge,0));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
}

/***** Fonction d'incrément minutes *******/ 
void RegleHorlogeMinutes ()
{ 
  minutesHorlogeINC = minutesHorloge + 1;  // additionne 1 à la valeur contenue dans la variable "minutes" et stocke le résultat dans la variable "minutesHorlogeINC"
  if (minutesHorlogeINC > 59)      // si la valeur de "minutesHorlogeINC" dépasse 59 (59min)
  {
    minutesHorlogeINC = 0;         // alors, met la variable "minutesHorlogeINC" à zero
  }
//    Serial.print(minutesHorlogeINC);
//    Serial.println(); 
    HORLOGE.adjust(DateTime(annee,mois,jour,heuresHorloge,minutesHorlogeINC,0));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
 }

/***** Régler l'Alarme 1 : Fonction Surveillance des BoutonAlarme1, BoutonMinutes et BoutonHeures *******/        
void SurveilleBouton_Alarme1_Heures_Minutes ()
{ 
  EtatBoutonHeures = digitalRead(BoutonHeures);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHeures"  
  EtatBoutonMinutes = digitalRead(BoutonMinutes);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonMinutes"
  EtatBoutonAlarme1 = digitalRead(BoutonAlarme1);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonMinutes"
  if ((EtatBoutonAlarme1 == LOW) && (EtatBoutonHeures == LOW))  // si le bouton est appuyé
    {
    delay(170);                     // alors,  attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleAlarm1Heures ();           // et appeller la fonction "RegleMinutes"
    }  
  if ((EtatBoutonAlarme1 == LOW) && (EtatBoutonMinutes == LOW))  // si le bouton est appuyé
    {  
    delay(170);                    // alors,  attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleAlarm1Minutes ();         // et appeller la fonction "RegleMinutes"
   }    
}

/***** Fonction d'incrément Alarme 1, Heures *******/ 
void RegleAlarm1Heures ()
{ 
  heuresAlarmeINC = heuresAlarme + 1;  // additionne 1 à la valeur contenue dans la variable "heures" et stocke le résultat dans la variable "heuresHorlogeINC"
  if (heuresAlarmeINC > 23)      // si la valeur de "heuresHorlogeINC" dépasse 23 (23h)
  {
    heuresAlarmeINC = 0;         // alors, et la variable "heuresHorlogeINC" à zero (minuit)
  }
//    Serial.print(minutesHorlogeINC);
//    Serial.println(); 
    RADIO.adjust(AlarmTime1(heuresAlarmeINC,minutesAlarme,0));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
} 
 
/***** Fonction d'incrément Alarme 1, Minutes *******/ 
void RegleAlarm1Minutes ()
{ 
  minutesAlarmeINC = minutesAlarme + 1;  // additionne 1 à la valeur contenue dans la variable "minutes" et stocke le résultat dans la variable "minutesHorlogeINC"
  if (minutesAlarmeINC > 59)      // si la valeur de "minutesHorlogeINC" dépasse 59 (59min)
  {
    minutesAlarmeINC = 0;         // alors, met la variable "minutesHorlogeINC" à zero
  }
//    Serial.print(minutesHorlogeINC);
//    Serial.println(); 
    RADIO.adjust(AlarmTime1(heuresAlarme,minutesAlarmeINC,0));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
}  

/***** Régler l'Alarme 2 : Fonction Surveillance des BoutonAlarme2, BoutonMinutes et BoutonHeures *******/  
void SurveilleBouton_Alarme2_Heures_Minutes ()
{ 
  EtatBoutonHeures = digitalRead(BoutonHeures);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHeures"  
  EtatBoutonMinutes = digitalRead(BoutonMinutes);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonMinutes"
  EtatBoutonAlarme2 = digitalRead(BoutonAlarme2);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonMinutes"
  if ((EtatBoutonAlarme2 == LOW) && (EtatBoutonHeures == LOW))  // si le bouton est appuyé
    {
    delay(170);                     // alors,  attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleAlarm2Heures ();           // et appeller la fonction "RegleMinutes"
    }  
  if ((EtatBoutonAlarme2 == LOW) && (EtatBoutonMinutes == LOW))  // si le bouton est appuyé
    {  
    delay(170);                    // alors,  attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleAlarm2Minutes ();         // et appeller la fonction "RegleMinutes"
   }    
}

/***** Fonction d'incrément Alarme 2, Heures *******/ 
void RegleAlarm2Heures ()
{ 
  heuresAlarmeINC = heuresAlarme + 1;  // additionne 1 à la valeur contenue dans la variable "heures" et stocke le résultat dans la variable "heuresHorlogeINC"
  if (heuresAlarmeINC > 23)      // si la valeur de "heuresHorlogeINC" dépasse 23 (23h)
  {
    heuresAlarmeINC = 0;         // alors, et la variable "heuresHorlogeINC" à zero (minuit)
  }
//    Serial.print(minutesHorlogeINC);
//    Serial.println(); 
    REVEIL.adjust(AlarmTime2(heuresAlarmeINC,minutesAlarme));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
} 
 
/***** Fonction d'incrément Alarme 2, Minutes *******/ 
void RegleAlarm2Minutes ()
{ 
  minutesAlarmeINC = minutesAlarme + 1;  // additionne 1 à la valeur contenue dans la variable "minutes" et stocke le résultat dans la variable "minutesHorlogeINC"
  if (minutesAlarmeINC > 59)      // si la valeur de "minutesHorlogeINC" dépasse 59 (59min)
  {
    minutesAlarmeINC = 0;         // alors, met la variable "minutesHorlogeINC" à zero
  }
//    Serial.print(minutesHorlogeINC);
//    Serial.println(); 
    REVEIL.adjust(AlarmTime2(heuresAlarme,minutesAlarmeINC));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
}  
  
 
/***** Fonction Surveillance des BoutonAlarme1 et Horloge *******/ 
void SurveilleBouton_Alarme1_Horloge ()
{ 
  EtatBoutonAlarme1 = digitalRead(BoutonAlarme1);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonAlarme1"
  EtatBoutonHorloge = digitalRead(BoutonHorloge);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHorloge"

  if ((EtatBoutonAlarme1 == LOW) && (EtatBoutonHorloge == LOW))  // si les boutons sont appuyé
  {
    delay(600);                     // alors, attendre 600 ms, permet un appuie bref pour activer ou désactiver l'alarme1 (radio)

      switch (RADIO.Alarm1Flag())    
     {
       case 0:  //  désactivée     // 0AH = 0xxxxxxx
         RADIO.Alarm1SetON();
         digitalWrite (LedAlarm1, HIGH);
         break;
       case 1:  // alarme activée     
        RADIO.Alarm1SetOFF();
        digitalWrite (LedAlarm1, LOW);     // 0AH = 1xxxxxxx
        break;
     }
  }
}

/***** Fonction Surveillance des BoutonAlarme2 et Horloge *******/ 
void SurveilleBouton_Alarme2_Horloge ()
{ 
  EtatBoutonAlarme2 = digitalRead(BoutonAlarme2);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonAlarme2"
  EtatBoutonHorloge = digitalRead(BoutonHorloge);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHorloge"

  if ((EtatBoutonAlarme2 == LOW) && (EtatBoutonHorloge == LOW))  // si le bouton est appuyé  
  {
    delay(600);                     // alors, attendre 600 ms, permet un appuie bref pour activer ou désactiver l'alarme2 (sonnerie)

      switch (REVEIL.Alarm2Flag())    
     {
       case 0:  // alarme désactivée     // 0AH = 0xxxxxxx
         REVEIL.Alarm2SetON();
         digitalWrite (LedAlarm2, HIGH);
         break;
  
      case 1:  // alarme activée     
        REVEIL.Alarm2SetOFF();
        digitalWrite (LedAlarm2, LOW);     // 0AH = 1xxxxxxx
        break;
     }
   }
}

/***** Fonction d'envoie d'ordre au GPIO du Rpi *******/ 
void RadioON()
{
  if (RADIO.Alarm1Status()==1)
  {
 //   digitalWrite(relais, HIGH);  # fait now par le RPI lui meme
    digitalWrite(Radio, LOW);
    delay(300);   // appuie bref
    digitalWrite(Radio, HIGH);
  //  delay(10000);
    change = 1;
  }
}

/***** Fonction d'activation de la sonnerie ChipTune *******/ 
void FaireSonnerSonnerie()
{
  
  if (REVEIL.Alarm2Status()==1)
  {
    digitalWrite(relais, HIGH);   // AmpliAudio alimenté
    delay(500);  // attendre quelques millisec entre chaque bouctle de sonnerie
    switch (song) {
    case 1:    // A-Team
      sonnerie(songA);
 //     song = song + 1;
      break;
    case 2:    // Hallowee
      sonnerie(songB);
 //     song = song + 1;
      break;
    case 3:    // Muppets
      sonnerie(songC);
 //     song = song + 1;
      break;
    case 4:    // TakeOnMe
      sonnerie(songD);
 //     song = song + 1;
      break;
    case 5:    // Gadget
      sonnerie(songE);
 //     song = song + 1;
      break;
   case 6:    // MahnaMahna
      sonnerie(songF);
 //     song = 1;
      break; 
   default: // cas par défaut 
      sonnerie(songA);
      break;     */
    }
  }
}

/***** Fonction pour stopper la sonneie  *******/ 
void stop2 ()  //appelée directement via l'interruption 0 lorsqu'on appuie sur le bouton alarm2
{
  change = 1;
  digitalWrite(relais, LOW);  // coupe l'alimentation de l'AmpliAudio
  // Serial.print(change); //
}

/***** Fonction d'ajustement de la luminosité via la photodiode *******/ 
void AjusteLuminosite()
{
  ValeurPhotoDiode = analogRead(photodiodepin);  // Lit la valeur renvoyée par la photodiode, et stocke la valeur dans la variable "ValeurPhotoDiode"
  if (ValeurPhotoDiode > 495)       // si la valeur est supérieure à 495 (beaucoup de lumière reçue, genre en plein jour)
  {
     analogWrite(ledPin, 255);      // alors, illumination des afficheurs et leds à 100% (PWM de 0 à 255)
  }
  else if (ValeurPhotoDiode > 462)  // sinon, si la valeur est supérieure à 462
  {
    analogWrite(ledPin, 238);       // alors, illumination des afficheurs et leds moins forte    
  }
  else if (ValeurPhotoDiode > 429)
  {
    analogWrite(ledPin, 221);
  }
  else if (ValeurPhotoDiode > 396)
  {
    analogWrite(ledPin, 204);
  }
  else if (ValeurPhotoDiode > 363)
  {
    analogWrite(ledPin, 187);
  }
    else if (ValeurPhotoDiode > 330)
  {
    analogWrite(ledPin, 170);
  }
    else if (ValeurPhotoDiode > 297)
  {
    analogWrite(ledPin, 153); 
  }
    else if (ValeurPhotoDiode > 264) 
  {
    analogWrite(ledPin, 136);
  }
    else if (ValeurPhotoDiode > 231)
  {
    analogWrite(ledPin, 119);
  }
    else if (ValeurPhotoDiode > 198)
  {
    analogWrite(ledPin, 102);
  }
    else if (ValeurPhotoDiode > 165)
  {
    analogWrite(ledPin, 85); 
  }
    else if (ValeurPhotoDiode > 132)
  {
    analogWrite(ledPin, 68);
  }
    else if (ValeurPhotoDiode > 99)
  {
    analogWrite(ledPin, 51); 
  }
    else if (ValeurPhotoDiode > 66)
  {
    analogWrite(ledPin, 34);
  }
    else if (ValeurPhotoDiode > 33)
  {
    analogWrite(ledPin, 17); 
  }
  else                             // sinon,  (très peu voire pas du tout de lumière reçue, genre dans la nuit)
  {
    analogWrite(ledPin, 8);        // alors, illumination des afficheurs et leds aux minimum 8
  } 
}

/***** Fonction Sonnerie *****/
void sonnerie(char *p)
{
  // Absolutely no error checking in here

  byte default_dur = 4;
  byte default_oct = 6;
  int bpm = 63;
  int num;
  long wholenote;
  long duration;
  byte note;
  byte scale;

  // format: d=N,o=N,b=NNN:
  // find the start (skip name, etc)

  while(*p != ':') p++;    // ignore name
  p++;                     // skip ':'

  // get default duration
  if(*p == 'd')
  {
    p++; p++;              // skip "d="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    if(num > 0) default_dur = num;
    p++;                   // skip comma
  }

//  Serial.print("ddur: "); Serial.println(default_dur, 10);

  // get default octave
  if(*p == 'o')
  {
    p++; p++;              // skip "o="
    num = *p++ - '0';
    if(num >= 3 && num <=7) default_oct = num;
    p++;                   // skip comma
  }

//  Serial.print("doct: "); Serial.println(default_oct, 10);

  // get BPM
  if(*p == 'b')
  {
    p++; p++;              // skip "b="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    bpm = num;
    p++;                   // skip colon
  }

//  Serial.print("bpm: "); Serial.println(bpm, 10);

  // BPM usually expresses the number of quarter notes per minute
  wholenote = (60 * 1000L / bpm) * 4;  // this is the time for whole note (in milliseconds)

//  Serial.print("wn: "); Serial.println(wholenote, 10);


  // now begin note loop
  while(*p)
  {
    // first, get note duration, if available
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    
    if(num) duration = wholenote / num;
    else duration = wholenote / default_dur;  // we will need to check if we are a dotted note after

    // now get the note
    note = 0;

    switch(*p)
    {
      case 'c':
        note = 1;
        break;
      case 'd':
        note = 3;
        break;
      case 'e':
        note = 5;
        break;
      case 'f':
        note = 6;
        break;
      case 'g':
        note = 8;
        break;
      case 'a':
        note = 10;
        break;
      case 'b':
        note = 12;
        break;
      case 'p':
      default:
        note = 0;
    }
    p++;

    // now, get optional '#' sharp
    if(*p == '#')
    {
      note++;
      p++;
    }

    // now, get optional '.' dotted note
    if(*p == '.')
    {
      duration += duration/2;
      p++;
    }
  
    // now, get scale
    if(isdigit(*p))
    {
      scale = *p - '0';
      p++;
    }
    else
    {
      scale = default_oct;
    }

    scale += OCTAVE_OFFSET;

    if(*p == ',')
      p++;       // skip comma for next note (or we may be at the end)

    // now play the note

    if(note)
    {
//      Serial.print("Playing: ");
//      Serial.print(scale, 10); Serial.print(' ');
//      Serial.print(note, 10); Serial.print(" (");
//      Serial.print(notes[(scale - 4) * 12 + note], 10);
//      Serial.print(") ");
//      Serial.println(duration, 10);
      tone1.play(notes[(scale - 4) * 12 + note]);
      delay(duration);
      tone1.stop();
    }
    else
    {
//      Serial.print("Pausing: ");
//      Serial.println(duration, 10);
      delay(duration);
    }
  }
}
  • Pour faire l'interface entre l'horloge et la radio, les signaux de commande de l'Arduino opérants en 5 Volts et ceux du Raspberry en 3 Volts, il manque ici une carte d'interface. Elle sera étudié au prochain billet sur le sujet.

Mode l'emploi de l'horloge :

De gauche à droite, les boutons : [Alarme 2] [Alarme 1] [Horloge] [Heures] [Minutes]

  • Pour régler l'heure :

Appuyer (bref ou long) sur [Horloge] + [Heures] , et sur [Horloge] + [Minutes]

  • Pour régler l'alarme 1 :

Appuyer (bref ou long) sur [Alarme 1] + [Heures] , et sur [Alarme 1] + [Minutes]

  • Pour régler l'alarme 2 :

Appuyer (bref ou long) sur [Alarme 2] + [Heures] , et sur [Alarme 2] + [Minutes]

  • Pour afficher l'alarme 1 :

Appuyer (bref) sur [Alarme 1]

  • Pour afficher l'alarme 2 :

Appuyer (bref) sur [Alarme 2]

  • Pour stopper la sonnerie :

Appuyer (bref) sur [Alarme 2]


À suivre…

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

Fil des commentaires de ce billet