Advertisement
bipping

step motor_V4.1

May 26th, 2024
610
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 34.03 KB | Source Code | 0 0
  1. #include <avr/interrupt.h>
  2. #include <Arduino.h>
  3. #include <Wire.h>
  4. #include <rgb_lcd.h>
  5. #include <EEPROM.h>
  6. #include <string.h>
  7. #include <avr/sleep.h>
  8. #include <avr/wdt.h>
  9.  
  10. //#define SDA A4
  11. //#define SLC A5
  12. // Constantes pour les notes jouées par le buzzer
  13. #define NOTE_CS6 1109
  14. #define NOTE_DS6 1245
  15.  
  16. // Variables globales pour les valeurs RGB de la LED
  17. const uint8_t VAL_RGB_R = 255;                            // Valeur R pour LED RGB
  18. const uint8_t VAL_RGB_G = 0;                              // Valeur G pour LED RGB
  19. const uint8_t VAL_RGB_B = 0;                              // Valeur B pour LED RGB
  20.  
  21. // Broches utilisées par le système
  22. const uint8_t PIN_SWITCH = 2;                             // interrupteur à bascule
  23. const uint8_t PIN_PWM_OUT = 3;                            // driver le ventilateur
  24. const uint8_t PIN_COURANT_COUPURE = 4;                    // détecte une coupure de courant
  25. const uint8_t PIN_LED_ROUGE = 5;                          // LED PIN_LED_ROUGE
  26. const uint8_t PIN_LED_ORANGE = 6;                         // LED PIN_LED_ORANGE
  27. const uint8_t PIN_LED_VERT = 7;                           // LED PIN_LED_VERTE
  28. const uint8_t PIN_MOTEUR_DIR = 8;                         // direction du moteur
  29. const uint8_t PIN_MOTEUR_ENA = 9;                         // activer/désactiver le frein du moteur
  30. const uint8_t PIN_MOTEUR_PUL = 10;                        // impulsions/vitesse du moteur
  31. const uint8_t PIN_BUZZER = 11;                            // Buzzer
  32. const uint8_t PIN_POTARD = A0;                            // potentiometre
  33. const uint8_t PIN_PWM_IN = A7;                            // Lecture de la température
  34.  
  35. // Intervalles de temps pour les actions en microsecondes
  36. const uint32_t INTERVAL_BASE = 3129;                      // interval de temps de base de 3129 µS pour une action
  37.  
  38. const uint32_t INTERVAL_MS_3 = 3;                         // interval de temps de base
  39. const uint32_t INTERVAL_MS_10 = 10;                       // 10 ms
  40. const uint32_t INTERVAL_MS_20 = 20;                       // 20 ms
  41. const uint32_t INTERVAL_MS_39 = 39;                       // 39 ms
  42. const uint32_t INTERVAL_MS_250 = 250;                     // 250 ms
  43. const uint32_t INTERVAL_MS_500 = 500;                     // 500 ms
  44. const uint32_t INTERVAL_S_1 = 1000;                       // 1 s
  45. const uint32_t INTERVAL_S_10 = 10000;                     // 10 s
  46.  
  47. const uint32_t LIMITEPASMAX = 120000;                     // Nombre maximal de pas du moteur
  48.  
  49. uint16_t potard;
  50. uint8_t ledPIN_LED;                              // Broche de la LED
  51. volatile uint32_t nombreDePas = 0;                        // Compteur de pas du moteur
  52. bool estCoupureCourant;                          // Vérifie si une sauvegarde est nécessaire lors d'une coupure de courant
  53. volatile bool direction;                                  // état virtuel de PIN_MOTEUR_DIR
  54. bool etatSwitch = false;                         // État virtuel de l'interupteur, défini sur enclancher (false)
  55. volatile bool blackout = false;                           // Flag pour indiquer une coupure de courant
  56. uint32_t LCD_interval = INTERVAL_MS_500;
  57.  
  58. // Motif personnalisé pour l'écran LCD
  59. byte L[8] = { 0b00000, 0b11000, 0b01100, 0b00100, 0b01100, 0b10010, 0b10001, 0b00000 }; // Motif personnalisé pour écran LCD
  60.  
  61. // Énumération pour les différents états
  62. enum Etat {
  63.   ETAT_DEMARAGE,
  64.  
  65.   ETAT_ORIGINE_INITIALIZATION,
  66.   ETAT_ORIGINE_MAIN,
  67.  
  68.   ETAT_AVANCE_INITIALIZATION,
  69.   ETAT_AVANCE_MAIN,
  70.  
  71.   ETAT_TRANSITION_AVANCE_TOGGLE,
  72.  
  73.   ETAT_TOGGLE_MAIN,
  74.   ETAT_TOGGLE_CHECKEXITCONDITION,
  75.  
  76.   ETAT_TOGGLE_RECUPERATION,
  77.  
  78.   ETAT_FAIL
  79. };
  80.  
  81. Etat etatActuel;                                          // Variable stockant l'état actuel du système
  82.  
  83. typedef void (*CallbackFunction)();                       // Définir un type de fonction de rappel
  84.  
  85. // Structure pour représenter une tâche
  86. struct Task {
  87.   void (*function)();    // Pointeur vers la fonction
  88.   uint32_t interval;     // Intervalle d'appel en microsecondes
  89.   uint32_t lastRunTime;  // Dernière exécution en microsecondes
  90.   bool active;           // État d'activation de la tâche
  91. };
  92.  
  93. // Structure pour représenter une tâche dans la file d'attente
  94. struct TaskQueue {
  95.   void (*function)();    // Pointeur vers la fonction
  96.   uint32_t runTime;      // Temps d'exécution prévu
  97. };
  98.  
  99. // Déclaration des fonctions gérées
  100. void updateSwitchState();
  101. void temperature();
  102. void LCD_update();
  103. void updatePotard();
  104. void checketatSwitch();
  105. void toggleBuzzer();
  106. void modulate_PIN_LED();
  107. //void toggle_PIN_MOTOR();
  108.  
  109.  
  110. // Déclaration des tâches
  111. Task tasks[] = {
  112.   {updateSwitchState, INTERVAL_MS_20, 0, true},
  113.   {temperature, INTERVAL_MS_39, 0, true},
  114.   {LCD_update, INTERVAL_MS_500, 0, false},
  115.   {updatePotard, INTERVAL_MS_250, 0, false},
  116.   {checketatSwitch, INTERVAL_MS_500, 0, false},
  117.   {toggleBuzzer, INTERVAL_MS_500, 0, false},
  118.   {modulate_PIN_LED, INTERVAL_MS_10, 0, false}
  119.   //{toggle_PIN_MOTOR, INTERVAL_BASE, 0, false}
  120. };
  121.  
  122. // Nombre de tâches
  123. const uint8_t numTasks = sizeof(tasks) / sizeof(tasks[0]);
  124.  
  125. // File d'attente pour les tâches
  126. TaskQueue taskQueue[10];
  127. uint8_t queueSize = 0;
  128.  
  129. rgb_lcd display; // Objet d'affichage LCD
  130.  
  131. ISR(TIMER4_OVF_vect) {
  132.   noInterrupts(); // Désactive les interruptions  
  133.   direction ? nombreDePas-- : nombreDePas++; // Décrémente ou incrémente le compteur de pas
  134.   interrupts(); // Réactive les interruptions
  135. }
  136.  
  137. void enableTimer4() {
  138.   TIMSK4 |= (1 << OCIE4A); // Activer l'interruption de comparaison pour OCR4A
  139. }
  140.  
  141. void disableTimer4() {
  142.   TIMSK4 &= ~(1 << OCIE4A); // Désactiver l'interruption de comparaison pour OCR4A
  143. }
  144.  
  145.  
  146. void setTimer4Interval(uint32_t intervalMicros) {
  147.   // Arrêter le Timer4
  148.   TCCR4B &= ~(1 << CS40);
  149.  
  150.   // Calculer la nouvelle valeur de comparaison (OCR4A) pour générer une interruption toutes les `intervalMicros` microsecondes
  151.   ICR4 = (16 * intervalMicros) - 1;
  152.  
  153.   // Redéfinir le duty cycle à 50%
  154.   OCR4B = ICR4 / 2;
  155.  
  156.   // Redémarrer le timer avec un prescaler de 1
  157.   TCCR4B |= (1 << CS40);
  158. }
  159.  
  160. // Sauvegarde les données essentielles dans EEPROM en cas de coupure de courant
  161. void interruptionCoupure() {
  162.   blackout = true;                                        // Indique une coupure de courant
  163. }
  164.  
  165. // Récupération des données après une coupure de courant
  166. void recuperation() {
  167.   uint32_t step;
  168.  
  169.   // Récupère le nombre de pas de EEPROM
  170.   EEPROM.get(0, step);                                  
  171.   nombreDePas = step;
  172.  
  173.   // Réinitialise le flag de coupure de courant dans l'EEPROM
  174.   EEPROM.update(4, false);
  175. }// Fin de recuperation
  176.  
  177. //sauvgarde les données importante si coupure detecter, arrete le programme
  178. void checketatFail() {
  179.   if(blackout || etatActuel == ETAT_FAIL){
  180.     cli();                                                // Désactive les interruptions globales.
  181.     wdt_disable();                                        // Désactive le watchdog timer
  182.  
  183.     bool spin =  estCoupureCourant;
  184.     uint32_t step = nombreDePas;
  185.  
  186.     // Sauvegarde le nombre de pas et l'état de coupure de courant dans l'EEPROM
  187.     EEPROM.update(0, step);                               // Sauvegarde le nombre de pas
  188.     EEPROM.update(4, spin);                               // Réinitialise le flag de coupure de courant
  189.  
  190.     // Désactive les sorties et signale l'état d'urgence
  191.     digitalWrite(PIN_MOTEUR_PUL, LOW);                    // Désactive les impulsions
  192.     digitalWrite(PIN_MOTEUR_ENA, HIGH);                   // Désactive le frein du moteur
  193.     digitalWrite(PIN_LED_ROUGE, HIGH);                    // Allume la LED rouge
  194.     LCD_Update_FAIL();
  195.     tone(PIN_BUZZER, NOTE_CS6, 1000);                     // Joue la note CS6
  196.  
  197.     // Boucle d'arrêt d'urgence
  198.     while(true) {
  199.       delay(4294967295);                                  // Bloque le système indéfiniment
  200.     }                                                    
  201.   }
  202. }
  203.  
  204. void executeTaskQueue() {
  205.   uint32_t currentTime = millis();  // Utiliser millis() pour une précision en millisecondes
  206.   for (uint8_t i = 0; i < queueSize; i++) {
  207.     if (taskQueue[i].runTime <= currentTime) {
  208.       taskQueue[i].function();
  209.       // Retirer la tâche de la file d'attente
  210.       for (uint8_t j = i; j < queueSize - 1; j++) {
  211.         taskQueue[j] = taskQueue[j + 1];
  212.       }
  213.       queueSize--;
  214.       i--;  // Ajuster l'indice pour la prochaine itération
  215.     }
  216.   }
  217. }
  218.  
  219. void addTaskToQueue(void (*function)(), uint32_t runTime) {
  220.   if (queueSize < sizeof(taskQueue) / sizeof(taskQueue[0])) {
  221.     taskQueue[queueSize].function = function;
  222.     taskQueue[queueSize].runTime = runTime;
  223.     queueSize++;
  224.   }
  225. }
  226.  
  227. void manageTask() {
  228.   uint32_t currentTime = millis();  // Obtenir le temps actuel en millisecondes
  229.   uint32_t nextTime = UINT32_MAX;   // Initialise le prochain temps d'exécution avec un maximum
  230.   const uint32_t margin = 1;       // Marge de sécurité en millisecondes
  231.  
  232.   // Parcourir les tâches pour trouver celles à ajouter à la file d'attente
  233.   for (uint8_t i = 0; i < numTasks; i++) {
  234.     if (tasks[i].active) {
  235.       uint32_t scheduledTime = tasks[i].lastRunTime + tasks[i].interval; // L'intervalle est en millisecondes
  236.       if (scheduledTime <= currentTime) {
  237.         // Ajouter la tâche à la file d'attente
  238.         addTaskToQueue(tasks[i].function, currentTime);
  239.         // Mettre à jour le dernier temps d'exécution
  240.         tasks[i].lastRunTime = currentTime;
  241.         scheduledTime = currentTime + tasks[i].interval;  // Reprogrammer la prochaine exécution
  242.       }
  243.       // Mettre à jour le prochain temps d'exécution global
  244.       if (scheduledTime < nextTime) {
  245.         nextTime = scheduledTime;
  246.       }
  247.     }
  248.   }
  249.  
  250.   // Calculer le temps jusqu'à la prochaine tâche
  251.   uint32_t timeToNextTask = nextTime - millis();
  252.   if (timeToNextTask > margin) {
  253.     timeToNextTask -= margin;  // Appliquer la marge de sécurité
  254.   } else {
  255.     timeToNextTask = 0;  // Éviter les valeurs négatives
  256.   }
  257.  
  258.   // Mettre en sommeil l'Arduino jusqu'à la prochaine tâche si aucune tâche n'est dans la file d'attente
  259.   if (queueSize == 0 && timeToNextTask > 0) {
  260.     delay(timeToNextTask);
  261.   }
  262. } // Fin de manageTask
  263.  
  264. void activateTask(void (*function)()) {
  265.   for (uint8_t i = 0; i < numTasks; i++) {
  266.     if (tasks[i].function == function) {
  267.       tasks[i].active = true;
  268.       break;
  269.     }
  270.   }
  271. }
  272.  
  273. void deactivateTask(void (*function)()) {
  274.   for (uint8_t i = 0; i < numTasks; i++) {
  275.     if (tasks[i].function == function) {
  276.       tasks[i].active = false;
  277.       break;
  278.     }
  279.   }
  280. }
  281.  
  282. void setTaskInterval(void (*function)(), uint32_t newInterval) {
  283.   for (uint8_t i = 0; i < numTasks; i++) {
  284.     if (tasks[i].function == function) {
  285.       tasks[i].interval = newInterval;
  286.       break;
  287.     }
  288.   }
  289. }
  290.  
  291. void LCD_Update_FAIL() {
  292.   display.clear();
  293.   display.setCursor(0, 0);
  294.   display.print("Erreur");
  295.   display.setCursor(0, 1);
  296.   display.print("Veuillez redemarrer");
  297.   display.display();
  298. }
  299.  
  300. void LCD_Update_DEMARAGE() {
  301.   display.clear();
  302.   display.setCursor(0, 0);
  303.   display.print("Mauvaise position");
  304.   display.setCursor(0, 1);
  305.   display.print("Enclancher l'interrupteur");
  306.   display.display();
  307. }
  308.  
  309. void LCD_Update_Steps() {
  310.   static uint32_t lastSteps = -1;
  311.  
  312.   if (lastSteps != nombreDePas) {
  313.     display.setCursor(8, 1);
  314.     display.print(nombreDePas);
  315.     lastSteps = nombreDePas;
  316.     LCD_interval = INTERVAL_MS_500;
  317.   }
  318.   display.display();
  319. }
  320.  
  321. void LCD_Update_Potard() {
  322.   static uint16_t lastPotValue = -1;
  323.  
  324.   if (lastPotValue != potard) {
  325.     display.setCursor(10, 1);
  326.     display.print(potard);
  327.     lastPotValue = potard;
  328.     LCD_interval = INTERVAL_MS_500;
  329.   }
  330.   display.display();
  331. }
  332.  
  333. void LCD_update() {
  334.   static Etat lastEtat = ETAT_DEMARAGE; // Initialiser avec un état par défaut
  335.  
  336.   // Mettre à jour l'affichage complet uniquement si l'état a changé
  337.   if (lastEtat != etatActuel) {
  338.     switch (etatActuel) {
  339.       case ETAT_DEMARAGE:
  340.         LCD_Update_DEMARAGE();
  341.         break;
  342.     case ETAT_ORIGINE_INITIALIZATION:
  343.         display.clear();
  344.         display.setCursor(0, 0);
  345.         display.print("Origine");
  346.         display.setCursor(0, 1);
  347.         display.print("Lambda: ");
  348.         break;
  349.       case ETAT_ORIGINE_MAIN:
  350.         LCD_Update_Potard();
  351.         break;
  352.       case ETAT_AVANCE_INITIALIZATION:
  353.         display.clear();
  354.         display.setCursor(0, 0);
  355.         display.print("Avance");
  356.         display.setCursor(0, 1);
  357.         display.print("Lambda: ");
  358.         break;
  359.       case ETAT_AVANCE_MAIN:
  360.         LCD_Update_Steps();
  361.         break;
  362.       case ETAT_TRANSITION_AVANCE_TOGGLE:
  363.         display.clear();
  364.         display.setCursor(0, 0);
  365.         display.print("Toggle");
  366.         display.setCursor(0, 1);
  367.         display.print("Lambda: ");
  368.         break;
  369.       case ETAT_TOGGLE_MAIN:
  370.         LCD_Update_Steps();
  371.         break;
  372.       case ETAT_FAIL:
  373.         LCD_Update_FAIL();
  374.         break;
  375.       default:
  376.         display.clear();
  377.         display.setCursor(0, 0);
  378.         display.print("Etat: ");
  379.         display.print(etatActuel);
  380.         break;
  381.     }
  382.     lastEtat = etatActuel;
  383.     display.display();
  384.     setTaskInterval(LCD_update, INTERVAL_MS_500);
  385.     LCD_interval = INTERVAL_MS_500;
  386.   }else{
  387.     LCD_interval = INTERVAL_MS_3 + LCD_interval;
  388.     if(LCD_interval <= INTERVAL_S_1 ){
  389.       setTaskInterval(LCD_update, LCD_interval);
  390.     }else{
  391.       setTaskInterval(LCD_update, INTERVAL_S_1); //
  392.     }
  393.   }
  394.   // Appeler les mises à jour spécifiques pour les états MAIN
  395.   switch (etatActuel) {
  396.     case ETAT_ORIGINE_MAIN:
  397.       LCD_Update_Potard();
  398.       break;
  399.     case ETAT_AVANCE_MAIN:
  400.       LCD_Update_Steps();
  401.       break;
  402.     case ETAT_TOGGLE_MAIN:
  403.       LCD_Update_Steps();
  404.       break;
  405.     default:
  406.       // Pas de mise à jour spécifique nécessaire
  407.       break;
  408.   }
  409. } // Fin de LCD_update
  410.  
  411. void setup() {
  412.   cli();                                                  // Désactive les interruptions globales pour la configuration initiale
  413.   Serial.begin(115200);                                   // Démarre la communication série à 115200 bps
  414.   display.begin(16, 2);                                   // Initialise l'écran LCD avec 16 colonnes et 2 lignes
  415.   display.setRGB(VAL_RGB_R, VAL_RGB_G, VAL_RGB_B);        // Définit la couleur de rétroéclairage de l'écran LCD
  416.   display.print("initialization");                        // Affiche le message d'initialisation sur l'écran LCD
  417.  
  418.   // Configuration des pins pour les LEDs et les sorties
  419.   pinMode(PIN_LED_ORANGE, OUTPUT);                        // Config. la LED orange en sortie
  420.   pinMode(PIN_LED_VERT, OUTPUT);                          // Config. la LED verte en sortie
  421.   pinMode(PIN_LED_ROUGE, OUTPUT);                         // Config. la LED rouge en sortie
  422.  
  423.   // Configuration des pins pour les entrées
  424.   pinMode(PIN_PWM_IN, INPUT);                             // Définit le pin A7 comme entrée pour la temperature
  425.   pinMode(PIN_POTARD, INPUT);                             // Définit le pin A0 comme entrée pour le potentiomètre
  426.   pinMode(PIN_SWITCH, INPUT_PULLUP);                      // Active la résistance de pull-up sur le pin du bouton
  427.   pinMode(PIN_MOTEUR_DIR, OUTPUT);                        // Config. la direction du moteur en sortie
  428.   pinMode(PIN_MOTEUR_PUL, OUTPUT);                        // Config. le pin de pulsation du moteur en sortie
  429.   pinMode(PIN_MOTEUR_ENA, OUTPUT);                        // Config. le pin d'activation du moteur en sortie
  430.   pinMode(PIN_BUZZER, OUTPUT);                            // Config. le pin du buzzer en sortie
  431.   pinMode(PIN_PWM_OUT, OUTPUT);                           // Config. le pin
  432.   pinMode(PIN_COURANT_COUPURE, INPUT_PULLUP);             // Active la résistance de pull-up pour la coupure de courant
  433.  
  434.   // Configuration initiale de l'état des sorties
  435.   digitalWrite(PIN_BUZZER, LOW);                          // Éteint le buzzer
  436.   digitalWrite(PIN_SWITCH, HIGH);                         // Initialise le PIN_SWITCH à l'état haut
  437.   digitalWrite(PIN_LED_VERT, HIGH);                       // Allume la LED verte
  438.   digitalWrite(PIN_LED_ORANGE, HIGH);                     // Allume la LED orange
  439.   digitalWrite(PIN_LED_ROUGE, HIGH);                      // Allume la LED rouge
  440.  
  441.   // Signal sonore d'initialisation
  442.   tone(PIN_BUZZER, NOTE_DS6, 500);                        // Joue un ton sur le buzzer
  443.   delay(500);                                             // Attend 500 ms
  444.  
  445.   // Éteint toutes les LEDs après le signal sonore
  446.   digitalWrite(PIN_LED_VERT, LOW);                        // Éteint la LED verte
  447.   digitalWrite(PIN_LED_ROUGE, LOW);                       // Éteint la LED rouge
  448.   digitalWrite(PIN_LED_ORANGE, LOW);                      // Éteint la LED orange
  449.  
  450.   // Vérifie et récupère l'état de coupure de courant depuis l'EEPROM
  451.   bool spin = false;
  452.   //EEPROM.get(4, spin);                       // Récupère l'état de coupure de courant de l'EEPROM
  453.   estCoupureCourant = spin;
  454.  
  455.   // Configuration de l'état initial du programme
  456.   etatActuel = (!estCoupureCourant) ? ETAT_DEMARAGE : ETAT_TOGGLE_RECUPERATION;
  457.  
  458.   // Configuration du Timer3
  459.   TCCR3A = _BV(COM3A1) | _BV(WGM31); // Fast PWM, 10-bit
  460.   TCCR3B = _BV(WGM33) | _BV(WGM32) | _BV(CS31); // Prescaler = 8
  461.   ICR3 = 0x03FF; // Valeur TOP pour un PWM 10-bit
  462.  
  463.   // Configuration initiale du Timer4
  464.   // Arrêter le Timer4
  465.   TCCR4A = 0;
  466.   TCCR4B = 0;
  467.   TCNT4  = 0;
  468.  
  469.   // Configuration du Timer4 en mode Fast PWM, 8 bits
  470.   TCCR4A = _BV(COM4B1) | _BV(WGM41); // Clear OC4B on compare match, Fast PWM
  471.   TCCR4B = _BV(WGM43) | _BV(WGM42) | _BV(CS40); // Fast PWM, prescaler = 1
  472.   ICR4 = 0xFF; // Valeur TOP pour un PWM 8 bits
  473.  
  474.  // Calculer la nouvelle valeur de comparaison (ICR4) pour générer un PWM avec l'intervalle toutes les INTERVAL_BASE microsecondes
  475.   ICR4 = (16 * INTERVAL_BASE) - 1;
  476.  
  477.   // Fixer le duty cycle à 50%
  478.   OCR4B = ICR4 / 2;
  479.  
  480.   // Activer l'interruption de débordement du Timer4
  481.   TIMSK4 |= _BV(TOIE4);
  482.  
  483.   // Configuration des interruptions
  484.   attachInterrupt(digitalPinToInterrupt(PIN_COURANT_COUPURE), interruptionCoupure, FALLING); // Interruption sur coupure de courant
  485.  
  486.   // Initial state configuration
  487.   updatePotard();                                         // Initialise le potentiomètre
  488.   updateSwitchState();                                    // Initialization de l'état de l'interupteur
  489.  
  490.   // Actions spécifiques en cas de coupure de courant
  491.   if (estCoupureCourant){
  492.     activateTask(checketatSwitch);
  493.     activateTask(toggleBuzzer);
  494.   }else{
  495.   ledPIN_LED = PIN_LED_ORANGE;
  496.   activateTask(modulate_PIN_LED);  
  497.   }
  498.  
  499.   delay(800);                                             // Court délai avant d'activer les interruptions et les tâches initiales
  500.  
  501.  
  502.   // Activation des tâches initiales
  503.   activateTask(LCD_update);
  504.   activateTask(updateSwitchState);
  505.  
  506.  
  507. // Configuration du watchdog timer
  508.   wdt_enable(WDTO_500MS);                                 // Configure the watchdog to timeout after 500 ms
  509.  
  510.   sei();                                                  // Active les interruptions globales
  511. }
  512.  
  513. void loop() {
  514.   wdt_reset(); // Reset the watchdog timer regularly
  515.   //updateSwitchState(); // est activé en permanance dans executeTaskQueue
  516.   //LCD_Update(); // est activé en permanance dans executeTaskQueue
  517.  
  518.   switch (etatActuel) {
  519.     case ETAT_DEMARAGE:
  520.       //modulate_PIN_LED(PIN_LED_ORANGE);
  521.       if(!etatSwitch) {
  522.         etatActuel = ETAT_ORIGINE_INITIALIZATION;
  523.       }
  524.       break;
  525.     case ETAT_ORIGINE_INITIALIZATION:
  526.       // Initialisations pour l'état d'origine
  527.       deactivateTask(toggleBuzzer);
  528.       deactivateTask(modulate_PIN_LED);
  529.  
  530.       activateTask(updatePotard);
  531.  
  532.       digitalWrite(PIN_LED_ORANGE, LOW);                  // Éteint la LED orange
  533.       digitalWrite(PIN_LED_ROUGE, HIGH);                  // Allume la LED rouge
  534.       ledPIN_LED = PIN_LED_VERT;
  535.  
  536.       activateTask(modulate_PIN_LED);
  537.  
  538.       digitalWrite(PIN_MOTEUR_ENA, HIGH);                 // Désactive le frein du moteur
  539.  
  540.       tone(PIN_BUZZER, NOTE_CS6, 80);                     // Joue la note CS6
  541.       delay(100);                                         // Pause de 100ms
  542.       tone(PIN_BUZZER, NOTE_DS6, 80);                     // Joue la note DS6
  543.       delay(100);                                         // Pause de 100ms
  544.       tone(PIN_BUZZER, NOTE_DS6, 160);                    // Joue la note DS6 plus longue
  545.       delay(250);                                         // Pause de 250ms
  546.  
  547.       digitalWrite(PIN_LED_ROUGE, LOW);                   // Éteint la LED rouge
  548.  
  549.       etatActuel = ETAT_ORIGINE_MAIN;                     // Définit l'état à ORIGINE
  550.       break;
  551.     case ETAT_ORIGINE_MAIN:
  552.      
  553.       if(etatSwitch) {
  554.  
  555.         etatActuel = ETAT_AVANCE_INITIALIZATION;
  556.       }
  557.       break;
  558.     case ETAT_AVANCE_INITIALIZATION:
  559.       // Initialisations pour l'état d'avance
  560.  
  561.  
  562.       deactivateTask(updatePotard);
  563.       deactivateTask(modulate_PIN_LED);      
  564.  
  565.       estCoupureCourant = true;                               // Réinitialise l'indicateur de coupure de courant
  566.       direction = false;
  567.  
  568.       digitalWrite(PIN_MOTEUR_DIR, LOW);                      // Définit le sens de rotation du moteur
  569.       digitalWrite(PIN_MOTEUR_ENA, LOW);                      // Active le moteur
  570.  
  571.       setTimer4Interval(static_cast<uint32_t>(potard));
  572.       enableTimer4();                                         // mise en marche du moteur
  573.  
  574.  
  575.       digitalWrite(PIN_LED_VERT, HIGH);                       // Allume la LED verte
  576.       digitalWrite(PIN_LED_ORANGE, LOW);                      // Éteint la LED orange
  577.       digitalWrite(PIN_LED_ROUGE, LOW);                       // Éteint la LED rouge
  578.  
  579.       etatActuel = ETAT_AVANCE_MAIN;                         // Définit l'état à AVANCE
  580.       break;
  581.     case ETAT_AVANCE_MAIN:
  582.       //Verifie si le programme doit s'arreter en urgence
  583.       checketatFail();
  584.  
  585.       if(nombreDePas >= LIMITEPASMAX || !etatSwitch) {
  586.         etatActuel = ETAT_TRANSITION_AVANCE_TOGGLE;
  587.       }
  588.       break;
  589.     case ETAT_TRANSITION_AVANCE_TOGGLE:
  590.       // Vérifie la condition de sortie de l'état d'avance
  591.       digitalWrite(PIN_LED_VERT, LOW);                        // Éteint la LED verte
  592.       disableTimer4();
  593.  
  594.       direction = true;
  595.       setTimer4Interval(INTERVAL_BASE);
  596.  
  597.       digitalWrite(PIN_MOTEUR_DIR, HIGH);                     // Change le sens de rotation du moteur
  598.       digitalWrite(PIN_MOTEUR_ENA, LOW);                      // Active le moteur
  599.  
  600.       enableTimer4();                                         // mise en marche du moteur
  601.       activateTask(checketatSwitch);
  602.  
  603.       etatActuel = ETAT_TOGGLE_MAIN;                          // Définit l'état à TOGGLE
  604.       break;
  605.     case ETAT_TOGGLE_MAIN:
  606.       //Verifie si le programme doit s'arreter en urgence
  607.       checketatFail();
  608.  
  609.       if(nombreDePas == 0){
  610.         etatActuel = ETAT_TOGGLE_CHECKEXITCONDITION;
  611.       }
  612.       break;
  613.     case ETAT_TOGGLE_CHECKEXITCONDITION:
  614.       // Vérifie la condition de sortie de l'état de toggle
  615.       deactivateTask(checketatSwitch);
  616.       disableTimer4();
  617.  
  618.       estCoupureCourant = false;                              // Réinitialise l'indicateur de coupure de courant
  619.       digitalWrite(PIN_LED_ORANGE, LOW);                      // Éteint la LED orange
  620.       digitalWrite(PIN_LED_VERT, LOW);                        // Éteint la LED verte
  621.  
  622.       etatActuel = (etatSwitch) ? ETAT_AVANCE_INITIALIZATION : ETAT_ORIGINE_INITIALIZATION;
  623.       break;
  624.     case ETAT_TOGGLE_RECUPERATION:    
  625.       recuperation();                                   // Appelle la fonction de récupération en cas de coupure
  626.  
  627.       etatActuel = ETAT_TRANSITION_AVANCE_TOGGLE;
  628.       break;
  629.     case ETAT_FAIL:
  630.       // Exécute la séquence d'arrêt d'urgence
  631.       checketatFail();
  632.  
  633.       break;
  634.     default: // ETAT_FAIL:
  635.       // Exécute la séquence d'arrêt d'urgence
  636.       etatActuel = ETAT_FAIL;
  637.       break;
  638.   }
  639.  
  640.   manageTask();
  641.   executeTaskQueue();
  642.  
  643. }//Fin de la boucle loop
  644.  
  645. /*/ Exécute une fonction à intervalle régulier basé sur un timer
  646. void checkTimerAndUpdate(uint16_t &previousTime, uint32_t intervalAction, CallbackFunction func) {
  647.   if (micros() - previousTime >= intervalAction ) {
  648.     previousTime = micros();                              // Réinitialise le temps précédent
  649.     func();                                               // Appelle la fonction passée en paramètre
  650.   }
  651. }// Fin de checkTimerAndUpdate*/
  652.  
  653. uint8_t OverSample_to_8bit(){
  654.   uint16_t sum = 0;
  655.   uint16_t add;
  656.   for(uint8_t i = 0; i < 4; i++) {
  657.     add = analogRead(PIN_PWM_IN);
  658.     //add = 65535 - add;                                    // Inverser le signal
  659.     add >>= 2;                                            // Diviser par 4 pour éviter le débordement de sum
  660.     sum += add;
  661.   }
  662.   uint8_t result = (uint8_t)(sum >> 4);                   // Diviser par 2^4 pour obtenir une moyenne sur 8 bits
  663.   if (result == 0xFF) {
  664.     return 0xFE;
  665.   } else {
  666.     return result;
  667.   }
  668. }
  669.  
  670. void temperature(){
  671.   const uint8_t SEUIL_ARRET = 2; // Valeur limite pour eteindre l'appareil lorsque la valeur convertie 16 bits de l'ADC est inferieure a cette valeur (equivalent a une valeur 10-bit de 10)
  672.   const uint8_t SEUIL_URGENCE = 21;// Valeur de declenchement pour le mode d'urgence lorsqu'une valeur est superieure de 5 degree par rapport a une valeur critique
  673.   const uint8_t SEUIL_DEGRER = 4;// Valeur equivalente a un degre pour la valeur convertie 16 bits de l'ADC
  674.   const uint16_t TIMER1_INTERVAL_COUNT = 255;
  675.   static bool run_fonctionnement_normal = false;
  676.   static bool isEmergencyMode = false;
  677.   static uint8_t timer1Count = 0;
  678.   static uint8_t isrCounter = 0;
  679.   static uint8_t ValeurSeuil = OverSample_to_8bit();
  680.   static uint8_t buffer_Temperature[32];
  681.   static uint8_t buffer_Time[32];
  682.   static uint8_t index = 0; // Index pour un tableau circulaire
  683.   static uint32_t incrementalInterval = INTERVAL_MS_3; //
  684.   static uint32_t newInterval = INTERVAL_MS_39 + incrementalInterval;
  685.  
  686.   uint8_t compteur = 0;
  687.   uint8_t validCount = 0;
  688.   uint8_t temp_ValeurSeuil = 0xFF;
  689.   bool variationcheck = false;
  690.   timer1Count += newInterval / INTERVAL_MS_39; // Mise à jour du compteur avec l'intervalle actuel
  691.   isrCounter += newInterval / INTERVAL_MS_39; // Mise à jour du compteur d'interruptions
  692.  
  693.   uint8_t adcValue_8bit = OverSample_to_8bit();
  694.   variationcheck = (adcValue_8bit != buffer_Temperature[index]);
  695.   buffer_Temperature[index] = adcValue_8bit;
  696.   buffer_Time[index] = 0;
  697.  
  698.   if (timer1Count >= TIMER1_INTERVAL_COUNT) {
  699.     timer1Count = 0;
  700.     run_fonctionnement_normal = true;
  701.   }
  702.  
  703.   for (uint8_t i = 0; i < 32; i++) {
  704.     if (buffer_Temperature[i] == 0xFF && buffer_Time[i] == 0xFF) continue;
  705.     validCount++;
  706.     if (!isEmergencyMode && variationcheck && buffer_Temperature[i] < ValeurSeuil) {
  707.       temp_ValeurSeuil = buffer_Temperature[i];
  708.     } else if (isEmergencyMode && (buffer_Temperature[i] - SEUIL_DEGRER) <= ValeurSeuil) {
  709.       compteur++;
  710.     }
  711.  
  712.     buffer_Time[i] += (i != index) * isrCounter; // Augmente le temps pour tous sauf l'index actuel
  713.     if (buffer_Time[i] >= 0xFF - isrCounter) {
  714.       buffer_Time[i] = 0xFE;
  715.       buffer_Temperature[i] = 0xFF;
  716.     }
  717.   }
  718.  
  719.   isrCounter = 0;
  720.   index = (index + 1) % 32; // Incrémente l'index circulairement
  721.  
  722.   // Ajustement de l'intervalle d'appel de la fonction
  723.  
  724.   if (isEmergencyMode) {
  725.     newInterval = INTERVAL_MS_39; // Réinitialiser l'intervalle en mode d'urgence
  726.     incrementalInterval = INTERVAL_MS_3; // Réinitialiser l'intervalle incrémental
  727.     if (compteur == validCount) {
  728.       isEmergencyMode = false;
  729.       OCR3A = 0xFF;
  730.     }
  731.   } else {
  732.     if (variationcheck) {
  733.       int32_t difference = abs((int)ValeurSeuil - (int)temp_ValeurSeuil);
  734.       ValeurSeuil = temp_ValeurSeuil;
  735.  
  736.       uint32_t x = incrementalInterval / INTERVAL_MS_3;
  737.       uint32_t reductionFactor = 1 + (uint32_t)difference; // Plus la différence est grande, plus le facteur de réduction est élevé
  738.       uint32_t y = x / reductionFactor ;
  739.       y = y > 0 ? y : 1;  // Assurer que y ne tombe pas en dessous de 1
  740.       uint32_t changeAmount  = y * INTERVAL_MS_3;
  741.       incrementalInterval = incrementalInterval - changeAmount;  // réduire l'intervalle sur changement de température
  742.       incrementalInterval = incrementalInterval > INTERVAL_MS_3 ? incrementalInterval : INTERVAL_MS_3; // Ne pas tomber sous INTERVAL_MS_3
  743.     }else {
  744.       uint32_t x = incrementalInterval / INTERVAL_MS_3;
  745.       uint32_t y = 2 * (x - 1) + 1; // Appliquer la formule y = 2(x-1) + 1
  746.       incrementalInterval = (y * INTERVAL_MS_3);
  747.       incrementalInterval = incrementalInterval < INTERVAL_S_10 ? incrementalInterval : INTERVAL_S_10; // Limite supérieure à 3182 secondes
  748.     }
  749.     newInterval = INTERVAL_MS_39 + incrementalInterval;
  750.     newInterval = newInterval < INTERVAL_MS_10  ? newInterval : INTERVAL_S_10 ; // Limite supérieure à 10 secondes
  751.  
  752.     if ((adcValue_8bit - ValeurSeuil) >= SEUIL_URGENCE) {
  753.       isEmergencyMode = true;
  754.     }
  755.  
  756.     if (run_fonctionnement_normal) {
  757.       static uint8_t duty_actuel = 0;
  758.       if (adcValue_8bit < SEUIL_ARRET) {
  759.         OCR3A = 0;
  760.       } else if (adcValue_8bit != duty_actuel && adcValue_8bit > SEUIL_ARRET) {
  761.         OCR3A = adcValue_8bit;
  762.         duty_actuel = adcValue_8bit;
  763.       }
  764.       run_fonctionnement_normal = false;
  765.     }
  766.   }
  767.   setTaskInterval(temperature, newInterval);
  768. }//Fin de temperature
  769.  
  770. //Fonction de mise à jour de potard et de la fréquence du PWM du moteur
  771. void updatePotard() {
  772.   uint16_t newPotard = map(analogRead(PIN_POTARD), 0, 1023, 11200, 11300); // Map la lecture analogique à la plage désirée
  773.   if (newPotard != potard) {                              // Vérifie si la valeur a changé
  774.     potard = newPotard;                                   // Met à jour la variable globale potard
  775.  
  776.   }
  777. }// Fin de updatePotard
  778.  
  779. // Met à jour l'état de l'interrupteur
  780. void updateSwitchState() {
  781.   static uint32_t lastChangeTime = 0;
  782.   static uint32_t currentInterval;  
  783.   uint32_t currentTime = millis();
  784.  
  785.  
  786.   if (digitalRead(PIN_SWITCH) != etatSwitch) {          // Vérifie si l'interrupteur à bascule a changé
  787.     etatSwitch = !etatSwitch;                           // Bascule l'état de l'interrupteur
  788.  
  789.     // Réinitialise l'intervalle d'appel après un changement d'état
  790.     currentInterval = INTERVAL_MS_20;                     // Réinitialise l'intervalle à une valeur moyenne
  791.     setTaskInterval(updateSwitchState, currentInterval);
  792.     lastChangeTime = currentTime;
  793.   } else {
  794.     // Ajuste l'intervalle en fonction du temps écoulé depuis le dernier changement d'état
  795.     if (currentTime - lastChangeTime > currentInterval) {
  796.       if (currentInterval < INTERVAL_S_1) {
  797.         currentInterval += INTERVAL_MS_10;          // Augmente l'intervalle si l'état n'a pas changé
  798.         currentInterval = min(currentInterval, INTERVAL_S_1); // S'assure de ne pas dépasser l'intervalle max
  799.       }
  800.       setTaskInterval(updateSwitchState, currentInterval);
  801.     } else {
  802.       if (currentInterval > INTERVAL_MS_20) {
  803.         currentInterval -= INTERVAL_MS_10;          // Réduit l'intervalle si l'état a changé
  804.         currentInterval = max(currentInterval, INTERVAL_MS_20); // S'assure de ne pas aller en dessous de l'intervalle min
  805.       }
  806.       setTaskInterval(updateSwitchState, currentInterval);
  807.     }
  808.   }
  809. }// Fin de updateSwitchState
  810.  
  811. // Fait varier la luminosité de la LED
  812. void modulate_PIN_LED() {
  813.   static uint8_t i = 1;                                   // Initialise l'intensité de la LED
  814.   static bool estIncrement = true;                        // Initialise la direction de l'incrémentation
  815.  
  816.   analogWrite(ledPIN_LED, i);
  817.  
  818.   i = estIncrement ? i + 1 : i - 1;                       // Incrémente ou décrémente la luminosité
  819.   if(i == 255 || i == 0) {                                // Verifie si i est arrivé au extremiter
  820.     estIncrement = !estIncrement;                         // Inverse la direction si les limites sont atteintes
  821.   }
  822. }// Fin de modulate_PIN_LED
  823.  
  824. // Fonction pour basculer l'état d'une broche
  825. void toggle(uint8_t pin) {
  826.   uint8_t port = digitalPinToPort(pin); // Obtenir le port de la broche
  827.   uint8_t bit = digitalPinToBitMask(pin); // Obtenir le bit de la broche
  828.  
  829.   // Obtenir l'adresse du registre de sortie pour le port
  830.   volatile uint8_t *out = portOutputRegister(port);
  831.  
  832.   // Bascule l'état de la broche en utilisant XOR
  833.   *out ^= bit;
  834. } // Fin de toggle
  835.  
  836. void toggleLEDVert() {
  837.     toggle(PIN_LED_VERT);
  838. }
  839.  
  840. void toggleLEDOrange() {
  841.     toggle(PIN_LED_ORANGE);
  842. }
  843.  
  844. // Exécute une action LED en fonction de l'état de l'interrupteur
  845. void checketatSwitch() {
  846.   etatSwitch = digitalRead(PIN_SWITCH); // Lire l'état de l'interrupteur
  847.   uint8_t ledPin = !etatSwitch ? PIN_LED_VERT : PIN_LED_ORANGE; // Déterminer quelle LED vérifier pour l'extinction
  848.   CallbackFunction func = etatSwitch ? toggleLEDVert : toggleLEDOrange; // Déterminer quelle fonction appeler pour basculer l'état de la LED
  849.  
  850.   if (digitalRead(ledPin) == HIGH) {
  851.     digitalWrite(ledPin, LOW); // Éteindre la LED si elle est allumée
  852.   }
  853.   func(); // Appeler la fonction de basculement de la LED
  854. }// Fin de checkTimerBasedOnState
  855.  
  856. //Actionne le moteur et décompte les pas
  857. /*void toggle_PIN_MOTOR() {
  858.   toggle(PIN_MOTEUR_PUL);                                 // Bascule le pin du moteur
  859.   noInterrupts();                                         // Désactive les interruptions
  860.   direction ? nombreDePas-- : nombreDePas++;              // Décrémente le compteur de pas
  861.   interrupts();                                           // Réactive les interruptions
  862. }// Fin de toggle_PIN_MOTOR*/
  863.  
  864. //tone utilise le Timer2
  865. void toggleBuzzer() {
  866.   static bool isActive = true;
  867.   if (isActive) {
  868.     noTone(PIN_BUZZER);                                   // Arrête le son pendant 84 millisecondes
  869.     isActive = false;                                     //
  870.   } else {
  871.     tone(PIN_BUZZER, NOTE_DS6, 160);                      // Joue la note DS6 pendant 160 millisecondes
  872.     isActive = true;
  873.   }
  874. }
  875.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement