
/* Programme pour tester entièrrement la platine d'expérimentation "UNIVERSELLE" pour carte NANO
   standart et afficheur OLED 1,3 pouces de diagonale.

 NOTE : C'est l'afficheur OLED qui pénalise le plus la rapidité de la boucle de base. C'est la raison pour
       laquelle un affichage n'est généré que si un paramètre a changé de valeur. Pour obtenir des mesures
       de tension en minimisant les fluctuations de numérisation, on procède à une intégration de 50 CAN.

 BRANCHEMENTS à effectuer :  L'afficheur est en place et les Straps conformément placés en fonction
 --------------------------  de la liste des manipulations proposées dans le didacticiel.
   • Ponder D9 à la LED verte de diamètre 3mm.
   • Ponter D10 à la LED verte de diamètre 5mm.
   • Enlever le strap et ponter D5 sur la LED rouge de diamètre 3mm.
   • Ponter D11 sur l'entrée du Darlington.
   • Ponter la sortie du potentiomètre sur A0.
   • Brancher un BP entre A1 et GND.
   • Brancher un BP entre A3 et GND. 

 UTILISATION du programme : Activer le Moniteur de l'IDE à 9600 baud.
 -------------------------- Les instructions sont entièrement listées sur le Moniteur.
  
Compilateur v1.7.9.             PGM               RAM dynamique
Programme NOYAU :         18584 Octets (60%)    502 Octets (24%) */

//------------------------ Constantes du programme --------------------------
#define Version "20/09/2025." // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#define Taille_PGM 15204 // Taille du programme. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#define Delai_ATT_Attente 8 // Durée d'affichage des événements. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#define Delai_voulu 50 // Demi période du clignottement en mS.

//------------------- Définition des broches binaires -----------------------
#define Orange_5mm 2 // La LED est pilotée par D2.
#define Sortie_D3 3 // // État alterné rapidement.
#define BUZZER 4 // Va sur le bruiteur actif.
#define Rouge_3mm 5 // La LED est pilotée par D5.
#define Rouge 6  // LED tricolore.
#define Vert 7 // LED tricolore.
#define Bleu 8 // LED tricolore.
#define Verte_3mm 9 // La LED est pilotée par D9.
#define Verte_5mm 10 // La LED est pilotée par D10.
#define Pilotage_TIP122 11 // D11 Pilote le Darlington de puissance par PWM.
#define Sortie_D12 12 // // État alterné rapidement.
#define LED_Arduino 13

//-------------------- Définition des broches analogiques -------------------
#define MESURE_U 14 // Tension vatiable sur A0.
#define BPA1 15 // Bouton poussoir sur A1.
#define Sortie_A2 16 // État alterné rapidement.
#define BPA3 17 // Bouton poussoir sur A3.

//---------------------- Déclarations pour le matériel ----------------------
#include "U8glib.h"   // L'afficheur est sur A4 et A5 pour SDA et SCL.
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);	// Usage de la ligne I2C (Two Wire Interface)

//------------------------- Variables du programme --------------------------
boolean Attente_Action;
byte Chrono_Attente_BP, Evenement, Frequence, Num_couleur, Num_LED;
int Compteur;
float SAV_Action, SAV_U, U; // Conversion en volts de la tension mesurée sur A0.
unsigned long TENSION;
unsigned long Temps_Ecoule_pour_clignoter = 0;
unsigned long Temps_Ecoule_pour_une_seconde = 0;

//========================= Procédures de servitude ============================
void BIP() {digitalWrite(BUZZER, HIGH); delay(100); digitalWrite(BUZZER, LOW);}

void Inverser_LED_Arduino() {digitalWrite(LED_Arduino,!digitalRead(LED_Arduino));}

int SRAM_LIBRE() { // Fonction qui retourne la taille de SRAM disponible.
    extern int __heap_start, *__brkval; // Déclaration des deux pointeurs dédiés.
    byte BIDON; // Dernière variable allouée, donc occupe le "haut" du TAS.
    if (__brkval == 0) {return (int) &BIDON -(int) &__heap_start;}
    else {return (int) &BIDON -(int) __brkval;}}

void Mesure_la_tension() { TENSION = 0;  // Mesure analogique CAN : [0 à 1023].
  for (int I = 0; I < 50; I++) {TENSION = TENSION + analogRead(MESURE_U);}
  TENSION = int(TENSION / 50); TENSION = map(TENSION, 0, 1023, 0, 50); U = float(TENSION/10.0);}

void Aff_presentation_sur_USB() {
  Serial.println(); Serial.println(F(" Logiciel pour tester la carte UNIVERSELLE."));
  Serial.println(F(" > Pour carte NANO simple <")); Serial.print  (F(" Version du "));
  Serial.println(Version); Serial.print(F(" Pile - Tas = ")); Serial.print(SRAM_LIBRE());
  Serial.println('.'); Serial.println();}

void Affiche_page_sur_OLED() {
  boolean Puce1; Puce1 = analogRead(20) > 512;
  boolean Puce2; Puce2 = analogRead(21) > 512;
  u8g.firstPage(); do {// Début de la boucle d'affichage de la page écran.
    if (Puce1) u8g.drawDisc(120,22,3); else u8g.drawCircle(120,22,3);
    if (Puce2) u8g.drawDisc(120,36,3); else u8g.drawCircle(120,36,3); 
    u8g.drawFrame(0,0,128,64);
    u8g.setPrintPos(10,6); u8g.print(F("Rev. du ")); u8g.print(Version);
    u8g.setPrintPos(10,20);
    if (Evenement == 0) {u8g.print(F("PILE - TAS = ")); u8g.print(SRAM_LIBRE());}
    else {u8g.print(F("Compteur = ")); u8g.print(Compteur);} u8g.print('.');
    u8g.setPrintPos(10,34); u8g.print(F("U sur A0 = ")); u8g.print(U,1); u8g.print("V.");
    u8g.drawFrame(106,47,19,11); u8g.setPrintPos(110,48); if (Frequence < 10) u8g.print('0');
    u8g.print(Frequence); u8g.setPrintPos(10,48);
    if (Chrono_Attente_BP == Delai_ATT_Attente) u8g.print(F("Attente Action."));
    else {switch(Evenement) {
         case 1 : {u8g.print(F("Action sur BPA1.")); break;}
         case 2 : u8g.print(F("Action sur BPA3."));}}}
 while(u8g.nextPage());}

void Eteindre_toutes_les_LEDs() {
  digitalWrite(Rouge, LOW); digitalWrite(Vert, LOW); digitalWrite(Bleu, LOW);
  digitalWrite(Rouge_3mm, HIGH); digitalWrite(Orange_5mm, HIGH); digitalWrite(Verte_3mm, LOW);
  digitalWrite(Verte_5mm, LOW);}

void Allume_LED_Multicolore() {
  switch (Num_couleur) {
    case 1 : {digitalWrite(Rouge, HIGH); break;}
    case 2 : {digitalWrite(Vert, HIGH); break;}
    case 3 : {digitalWrite(Rouge, HIGH); digitalWrite(Vert, HIGH);break;}
    case 4 : {digitalWrite(Bleu, HIGH); break;}
    case 5 : {digitalWrite(Rouge, HIGH); digitalWrite(Bleu, HIGH);break;}
    case 6 : {digitalWrite(Vert, HIGH); digitalWrite(Bleu, HIGH);break;}
    case 7 : {digitalWrite(Rouge, HIGH); digitalWrite(Vert, HIGH); break; digitalWrite(Bleu, HIGH);}}}

void Modifie_la_frequence() {
  if (Evenement == 1) if (Frequence < 10) Frequence++;
  if (Evenement == 2) if (Frequence > 1) Frequence--;
  tone(Pilotage_TIP122, Frequence * 100); BIP();}

void Gere_les_BP() {// L'antirebonds est rudimentaire dans ce démonstrateur et réduit à un simple delai.
  byte SAV_Evenement = Evenement; Evenement = 0;
  if (analogRead(BPA1) < 511) {
     Serial.println(); Serial.print(F(" BP sur A1 activ")); Serial.print(char(233)); Evenement = 1;
     //---------------- Attendre le relâcher ----------------
     while(analogRead(BPA1) < 511); delay(50);} // Ne rien faire.
  //--------------------- Vérifier un clic sur le BPA3 ----------------------
  if (analogRead(BPA3) < 511) {
     Serial.println(); Serial.print(F(" BP sur A3 activ")); Serial.print(char(233)); Evenement = 2;
     //---------------- Attendre le relâcher ----------------
     while(analogRead(BPA3) < 511); delay(50);} // Ne rien faire.
  if (Evenement > 0) {Chrono_Attente_BP = 0; Modifie_la_frequence();} else Evenement = SAV_Evenement;}

void Alterne_les_sorties() {
  digitalWrite(Sortie_D3,!digitalRead(Sortie_D3));
  digitalWrite(Sortie_D12,!digitalRead(Sortie_D12));
  digitalWrite(Sortie_A2,!digitalRead(Sortie_A2));}

void Aff_les_manipulations() {
  Serial.print(char(149)); Serial.print(F(" Les branchements indiqu"));
  Serial.print(char(233)); Serial.print(F("s en t")); Serial.print(char(234));
  Serial.println(F("te de listage sont effectifs."));
  Serial.println(F("  (C'est important pour conduire les essais."));
  Serial.print(char(149)); Serial.println(F(" Sur RESET la ligne 2 de l'afficheur indique PILE-TAS."));
  Serial.print(char(149)); Serial.println(F(" La LED Arduino clignote en permanence."));
  Serial.print(char(149)); Serial.print(F(" Les LEDs s'illuminent les unes apr"));
  Serial.print(char(232)); Serial.println(F("s les autres."));
  Serial.print(char(149)); Serial.print(F(" La LED tricolore change de couleur "));
  Serial.print(char(224)); Serial.println(F(" chaque cycle.")); Serial.print(char(149));
  Serial.print(F(" Le petit carr")); Serial.print(char(233)); Serial.print(F(" en bas "));
  Serial.print(char(224)); Serial.println(F(" droite indique en Khz/100"));
  Serial.print(F("  la fr")); Serial.print(char(233)); Serial.print(F("quence de d"));
  Serial.print(char(233)); Serial.println(F("coupage sur D11 pilotant le TIP122."));
  Serial.print(char(149)); Serial.print(F(" La tension fournie par le potentiom"));
  Serial.print(char(232)); Serial.print(F("tre est affich")); Serial.print(char(233));
  Serial.println(F("e")); Serial.print(F("  en permanence sur la troisi")); Serial.print(char(232));
  Serial.print(F("me ligne de l'")); Serial.print(char(233)); Serial.println(F("cran OLED."));
  Serial.print(char(149)); Serial.print(F(" Chaque clic sur un BP est indiqu"));
  Serial.print(char(233)); Serial.println(F(" sur la ligne du bas"));
  Serial.print(F("  durant quelques secondes et la fr")); Serial.print(char(233));
  Serial.print(F("quence est modifi")); Serial.print(char(233)); Serial.println(F("e :"));
  Serial.println(F("  BP1 augmente de 1, BP2 diminue de 1. Maximum 10."));
  Serial.print(F("  Le d")); Serial.print(char(233)); Serial.print(F("coupage est "));
  Serial.print(char(224)); Serial.println(F(" cette valeur x 100."));
  Serial.print(char(149)); Serial.println(F(" Chaque clic sur un BP provoque un BIP sonore."));
  Serial.print(char(149)); Serial.print(F(" D")); Serial.print(char(232));
  Serial.print(F("s qu'un BP a ")); Serial.print(char(233)); Serial.print('t');
  Serial.print(char(233)); Serial.print(F(" cliqu")); Serial.print(char(233));
  Serial.print(F(", la deuxi")); Serial.print(char(232)); Serial.print(F("me ligne pr"));
  Serial.print(char(233)); Serial.println(F("cise le"));
  Serial.print(F("  nombre de cycles effectu")); Serial.print(char(233)); Serial.println(F("s."));
  Serial.print(char(149)); Serial.println(F(" A6 pilote la puce du haut, A7 celle du bas."));
  Serial.println(); Serial.println(F("        Manipulations a effectuer :"));
  Serial.println(F("        ==========================="));
  Serial.print(F("* Ponter A6 sur GND puis sur +Vcc. La puce du haut doit changer d'"));
  Serial.print(char(233)); Serial.println(F("tat."));
  Serial.print(F("* Ponter A7 sur GND puis sur +Vcc. La puce du bas doit changer d'"));
  Serial.print(char(233)); Serial.println(F("tat."));
  Serial.print(F("* Tourner le potentiom"));
  Serial.print(char(232)); Serial.print(F("tre, la tension doit changer lin"));
  Serial.print(char(233)); Serial.println(F("airement.")); Serial.print(F("* Par exemple d"));
  Serial.print(char(233)); Serial.print(F("brancher D10 pour disposer d'un t"));
  Serial.print(char(233)); Serial.println(F("moin logique puis :"));
  Serial.print(F("* Tester le clignotement sur D3, D7 et D8 en parall"));
  Serial.print(char(232)); Serial.println(F("le avec Rouge/Vert/Bleu."));
  Serial.print(F("* Tester l'")); Serial.print(char(233));
  Serial.println(F("clairement sur D6, D12, D13 et A2."));
  Serial.print(F("* Sur la sortie +3,3v et la sortie +5V le t"));
  Serial.print(char(233)); Serial.println(F("moin doit s'allumer."));
  Serial.print(F("* D")); Serial.print(char(233));
  Serial.println(F("brancher D5 et tester le collecteur du TIP 122. La LED rouge s'allume."));
  Serial.print(F("* Lib")); Serial.print(char(233)); Serial.print(F("rer les deux supports sp"));
  Serial.print(char(233)); Serial.print(F("cialis")); Serial.print(char(233));
  Serial.print(F("s et y ins")); Serial.print(char(233)); Serial.println(F("rer deux modules BLUETOOTH"));
  Serial.print(F("  appair")); Serial.print(char(233));
  Serial.println(F("s. Au bout de 7 secondes ils doivent allumer les deux LEDs vertes.")); 
  Serial.print(F("* DEBRANCHER la mini USB. Placer 9Vcc sur VIN : Le syst"));
  Serial.print(char(232)); Serial.println(F("me doit fonctionner."));
  Serial.println(F("  -----------------------"));
  Serial.print(F("* DEBRANCHER VIN. Forcer 5Vcc sur le picot +Vcc : Le syst"));
  Serial.print(char(232)); Serial.println(F("me doit fonctionner."));
  Serial.println(F("* >>> Fin des tests et VALIDATION du circuit universel acquise ... OUF !"));}

//========================= Corps du programme ===============================

void setup() {
  Serial.begin(9600); Aff_presentation_sur_USB(); Aff_les_manipulations();
  pinMode(LED_Arduino,OUTPUT); pinMode(Rouge_3mm,OUTPUT); pinMode(Verte_3mm,OUTPUT);
  pinMode(Orange_5mm,OUTPUT); pinMode(Verte_5mm,OUTPUT); pinMode(BUZZER,OUTPUT); digitalWrite(BUZZER,LOW);
  pinMode(Sortie_D3,OUTPUT); pinMode(Sortie_D12,OUTPUT); pinMode(Sortie_A2,OUTPUT);
  // Avec l'utilisation de TONE inutile d'ajouter pinMode(Pilotage_TIP122,OUTPUT) dans le programme.
  u8g.setFont(u8g_font_6x10); u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor(); u8g.setFontPosTop();
  //------------------ Initialisation des variables ------------------
  Attente_Action = true; Compteur = 0; Chrono_Attente_BP = Delai_ATT_Attente; Evenement = 0;
  Frequence = 1; Num_couleur = 1; Num_LED = 1; SAV_Action = 0; SAV_U = 0; tone(Pilotage_TIP122,1000);}

void loop() {
  //--------------------- Vérifier un clic sur le BPA1 ----------------------
  Gere_les_BP(); // Mis en procédure pour "raccourcir" le listage de la boucle de base.
  //-------------------------------------------------------------------------
  Mesure_la_tension();
  if ((U != SAV_U) || (Evenement != SAV_Action)) {Affiche_page_sur_OLED();
     SAV_U = U; SAV_Action = Evenement;} // Prise en compte des actions.
  //====================== Chronométrage pour clignoter =====================
  if (millis() - Temps_Ecoule_pour_clignoter > Delai_voulu)  {
     Temps_Ecoule_pour_clignoter = millis(); Inverser_LED_Arduino(); Alterne_les_sorties();}
  //=============== Chronométrage pour un délai d'une seconde ===============
  //============ Chronométrage pour un délai d'une demi seconde =============
  if (millis() - Temps_Ecoule_pour_une_seconde > 500)  {
  Temps_Ecoule_pour_une_seconde = millis(); Eteindre_toutes_les_LEDs(); 
  switch (Num_LED) {
    case 1 : {Allume_LED_Multicolore(); break;}
    case 2 : {digitalWrite(Verte_3mm, HIGH); break;}
    case 3 : {digitalWrite(Rouge_3mm, LOW); break;} // Pilotée en logique négative.
    case 4 : {digitalWrite(Orange_5mm, LOW); break;} // Pilotée en logique négative.
    case 5 : digitalWrite(Verte_5mm, HIGH);}
  Num_couleur++; if (Num_couleur == 8) Num_couleur = 1; Num_LED++; if (Num_LED == 6) Num_LED = 1;
  Compteur++; Affiche_page_sur_OLED(); if (Chrono_Attente_BP < Delai_ATT_Attente) Chrono_Attente_BP++;}}




