Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <avr/interrupt.h>
- #include <Arduino.h>
- #include <Wire.h>
- #include <rgb_lcd.h>
- #include <EEPROM.h>
- #include <string.h>
- #include <avr/sleep.h>
- #include <avr/wdt.h>
- //#define SDA A4
- //#define SLC A5
- // Constantes pour les notes jouées par le buzzer
- #define NOTE_CS6 1109
- #define NOTE_DS6 1245
- // Variables globales pour les valeurs RGB de la LED
- const uint8_t VAL_RGB_R = 255; // Valeur R pour LED RGB
- const uint8_t VAL_RGB_G = 0; // Valeur G pour LED RGB
- const uint8_t VAL_RGB_B = 0; // Valeur B pour LED RGB
- // Broches utilisées par le système
- const uint8_t PIN_SWITCH = 2; // interrupteur à bascule
- const uint8_t PIN_PWM_OUT = 3; // driver le ventilateur
- const uint8_t PIN_COURANT_COUPURE = 4; // détecte une coupure de courant
- const uint8_t PIN_LED_ROUGE = 5; // LED PIN_LED_ROUGE
- const uint8_t PIN_LED_ORANGE = 6; // LED PIN_LED_ORANGE
- const uint8_t PIN_LED_VERT = 7; // LED PIN_LED_VERTE
- const uint8_t PIN_MOTEUR_DIR = 8; // direction du moteur
- const uint8_t PIN_MOTEUR_ENA = 9; // activer/désactiver le frein du moteur
- const uint8_t PIN_MOTEUR_PUL = 10; // impulsions/vitesse du moteur
- const uint8_t PIN_BUZZER = 11; // Buzzer
- const uint8_t PIN_POTARD = A0; // potentiometre
- const uint8_t PIN_PWM_IN = A7; // Lecture de la température
- // Intervalles de temps pour les actions en microsecondes
- const uint32_t INTERVAL_BASE = 3129; // interval de temps de base de 3129 µS pour une action
- const uint32_t INTERVAL_MS_3 = 3; // interval de temps de base
- const uint32_t INTERVAL_MS_10 = 10; // 10 ms
- const uint32_t INTERVAL_MS_20 = 20; // 20 ms
- const uint32_t INTERVAL_MS_39 = 39; // 39 ms
- const uint32_t INTERVAL_MS_250 = 250; // 250 ms
- const uint32_t INTERVAL_MS_500 = 500; // 500 ms
- const uint32_t INTERVAL_S_1 = 1000; // 1 s
- const uint32_t INTERVAL_S_10 = 10000; // 10 s
- const uint32_t LIMITEPASMAX = 120000; // Nombre maximal de pas du moteur
- uint16_t potard;
- uint8_t ledPIN_LED; // Broche de la LED
- volatile uint32_t nombreDePas = 0; // Compteur de pas du moteur
- bool estCoupureCourant; // Vérifie si une sauvegarde est nécessaire lors d'une coupure de courant
- volatile bool direction; // état virtuel de PIN_MOTEUR_DIR
- bool etatSwitch = false; // État virtuel de l'interupteur, défini sur enclancher (false)
- volatile bool blackout = false; // Flag pour indiquer une coupure de courant
- uint32_t LCD_interval = INTERVAL_MS_500;
- // Motif personnalisé pour l'écran LCD
- byte L[8] = { 0b00000, 0b11000, 0b01100, 0b00100, 0b01100, 0b10010, 0b10001, 0b00000 }; // Motif personnalisé pour écran LCD
- // Énumération pour les différents états
- enum Etat {
- ETAT_DEMARAGE,
- ETAT_ORIGINE_INITIALIZATION,
- ETAT_ORIGINE_MAIN,
- ETAT_AVANCE_INITIALIZATION,
- ETAT_AVANCE_MAIN,
- ETAT_TRANSITION_AVANCE_TOGGLE,
- ETAT_TOGGLE_MAIN,
- ETAT_TOGGLE_CHECKEXITCONDITION,
- ETAT_TOGGLE_RECUPERATION,
- ETAT_FAIL
- };
- Etat etatActuel; // Variable stockant l'état actuel du système
- typedef void (*CallbackFunction)(); // Définir un type de fonction de rappel
- // Structure pour représenter une tâche
- struct Task {
- void (*function)(); // Pointeur vers la fonction
- uint32_t interval; // Intervalle d'appel en microsecondes
- uint32_t lastRunTime; // Dernière exécution en microsecondes
- bool active; // État d'activation de la tâche
- };
- // Structure pour représenter une tâche dans la file d'attente
- struct TaskQueue {
- void (*function)(); // Pointeur vers la fonction
- uint32_t runTime; // Temps d'exécution prévu
- };
- // Déclaration des fonctions gérées
- void updateSwitchState();
- void temperature();
- void LCD_update();
- void updatePotard();
- void checketatSwitch();
- void toggleBuzzer();
- void modulate_PIN_LED();
- //void toggle_PIN_MOTOR();
- // Déclaration des tâches
- Task tasks[] = {
- {updateSwitchState, INTERVAL_MS_20, 0, true},
- {temperature, INTERVAL_MS_39, 0, true},
- {LCD_update, INTERVAL_MS_500, 0, false},
- {updatePotard, INTERVAL_MS_250, 0, false},
- {checketatSwitch, INTERVAL_MS_500, 0, false},
- {toggleBuzzer, INTERVAL_MS_500, 0, false},
- {modulate_PIN_LED, INTERVAL_MS_10, 0, false}
- //{toggle_PIN_MOTOR, INTERVAL_BASE, 0, false}
- };
- // Nombre de tâches
- const uint8_t numTasks = sizeof(tasks) / sizeof(tasks[0]);
- // File d'attente pour les tâches
- TaskQueue taskQueue[10];
- uint8_t queueSize = 0;
- rgb_lcd display; // Objet d'affichage LCD
- ISR(TIMER4_OVF_vect) {
- noInterrupts(); // Désactive les interruptions
- direction ? nombreDePas-- : nombreDePas++; // Décrémente ou incrémente le compteur de pas
- interrupts(); // Réactive les interruptions
- }
- void enableTimer4() {
- TIMSK4 |= (1 << OCIE4A); // Activer l'interruption de comparaison pour OCR4A
- }
- void disableTimer4() {
- TIMSK4 &= ~(1 << OCIE4A); // Désactiver l'interruption de comparaison pour OCR4A
- }
- void setTimer4Interval(uint32_t intervalMicros) {
- // Arrêter le Timer4
- TCCR4B &= ~(1 << CS40);
- // Calculer la nouvelle valeur de comparaison (OCR4A) pour générer une interruption toutes les `intervalMicros` microsecondes
- ICR4 = (16 * intervalMicros) - 1;
- // Redéfinir le duty cycle à 50%
- OCR4B = ICR4 / 2;
- // Redémarrer le timer avec un prescaler de 1
- TCCR4B |= (1 << CS40);
- }
- // Sauvegarde les données essentielles dans EEPROM en cas de coupure de courant
- void interruptionCoupure() {
- blackout = true; // Indique une coupure de courant
- }
- // Récupération des données après une coupure de courant
- void recuperation() {
- uint32_t step;
- // Récupère le nombre de pas de EEPROM
- EEPROM.get(0, step);
- nombreDePas = step;
- // Réinitialise le flag de coupure de courant dans l'EEPROM
- EEPROM.update(4, false);
- }// Fin de recuperation
- //sauvgarde les données importante si coupure detecter, arrete le programme
- void checketatFail() {
- if(blackout || etatActuel == ETAT_FAIL){
- cli(); // Désactive les interruptions globales.
- wdt_disable(); // Désactive le watchdog timer
- bool spin = estCoupureCourant;
- uint32_t step = nombreDePas;
- // Sauvegarde le nombre de pas et l'état de coupure de courant dans l'EEPROM
- EEPROM.update(0, step); // Sauvegarde le nombre de pas
- EEPROM.update(4, spin); // Réinitialise le flag de coupure de courant
- // Désactive les sorties et signale l'état d'urgence
- digitalWrite(PIN_MOTEUR_PUL, LOW); // Désactive les impulsions
- digitalWrite(PIN_MOTEUR_ENA, HIGH); // Désactive le frein du moteur
- digitalWrite(PIN_LED_ROUGE, HIGH); // Allume la LED rouge
- LCD_Update_FAIL();
- tone(PIN_BUZZER, NOTE_CS6, 1000); // Joue la note CS6
- // Boucle d'arrêt d'urgence
- while(true) {
- delay(4294967295); // Bloque le système indéfiniment
- }
- }
- }
- void executeTaskQueue() {
- uint32_t currentTime = millis(); // Utiliser millis() pour une précision en millisecondes
- for (uint8_t i = 0; i < queueSize; i++) {
- if (taskQueue[i].runTime <= currentTime) {
- taskQueue[i].function();
- // Retirer la tâche de la file d'attente
- for (uint8_t j = i; j < queueSize - 1; j++) {
- taskQueue[j] = taskQueue[j + 1];
- }
- queueSize--;
- i--; // Ajuster l'indice pour la prochaine itération
- }
- }
- }
- void addTaskToQueue(void (*function)(), uint32_t runTime) {
- if (queueSize < sizeof(taskQueue) / sizeof(taskQueue[0])) {
- taskQueue[queueSize].function = function;
- taskQueue[queueSize].runTime = runTime;
- queueSize++;
- }
- }
- void manageTask() {
- uint32_t currentTime = millis(); // Obtenir le temps actuel en millisecondes
- uint32_t nextTime = UINT32_MAX; // Initialise le prochain temps d'exécution avec un maximum
- const uint32_t margin = 1; // Marge de sécurité en millisecondes
- // Parcourir les tâches pour trouver celles à ajouter à la file d'attente
- for (uint8_t i = 0; i < numTasks; i++) {
- if (tasks[i].active) {
- uint32_t scheduledTime = tasks[i].lastRunTime + tasks[i].interval; // L'intervalle est en millisecondes
- if (scheduledTime <= currentTime) {
- // Ajouter la tâche à la file d'attente
- addTaskToQueue(tasks[i].function, currentTime);
- // Mettre à jour le dernier temps d'exécution
- tasks[i].lastRunTime = currentTime;
- scheduledTime = currentTime + tasks[i].interval; // Reprogrammer la prochaine exécution
- }
- // Mettre à jour le prochain temps d'exécution global
- if (scheduledTime < nextTime) {
- nextTime = scheduledTime;
- }
- }
- }
- // Calculer le temps jusqu'à la prochaine tâche
- uint32_t timeToNextTask = nextTime - millis();
- if (timeToNextTask > margin) {
- timeToNextTask -= margin; // Appliquer la marge de sécurité
- } else {
- timeToNextTask = 0; // Éviter les valeurs négatives
- }
- // Mettre en sommeil l'Arduino jusqu'à la prochaine tâche si aucune tâche n'est dans la file d'attente
- if (queueSize == 0 && timeToNextTask > 0) {
- delay(timeToNextTask);
- }
- } // Fin de manageTask
- void activateTask(void (*function)()) {
- for (uint8_t i = 0; i < numTasks; i++) {
- if (tasks[i].function == function) {
- tasks[i].active = true;
- break;
- }
- }
- }
- void deactivateTask(void (*function)()) {
- for (uint8_t i = 0; i < numTasks; i++) {
- if (tasks[i].function == function) {
- tasks[i].active = false;
- break;
- }
- }
- }
- void setTaskInterval(void (*function)(), uint32_t newInterval) {
- for (uint8_t i = 0; i < numTasks; i++) {
- if (tasks[i].function == function) {
- tasks[i].interval = newInterval;
- break;
- }
- }
- }
- void LCD_Update_FAIL() {
- display.clear();
- display.setCursor(0, 0);
- display.print("Erreur");
- display.setCursor(0, 1);
- display.print("Veuillez redemarrer");
- display.display();
- }
- void LCD_Update_DEMARAGE() {
- display.clear();
- display.setCursor(0, 0);
- display.print("Mauvaise position");
- display.setCursor(0, 1);
- display.print("Enclancher l'interrupteur");
- display.display();
- }
- void LCD_Update_Steps() {
- static uint32_t lastSteps = -1;
- if (lastSteps != nombreDePas) {
- display.setCursor(8, 1);
- display.print(nombreDePas);
- lastSteps = nombreDePas;
- LCD_interval = INTERVAL_MS_500;
- }
- display.display();
- }
- void LCD_Update_Potard() {
- static uint16_t lastPotValue = -1;
- if (lastPotValue != potard) {
- display.setCursor(10, 1);
- display.print(potard);
- lastPotValue = potard;
- LCD_interval = INTERVAL_MS_500;
- }
- display.display();
- }
- void LCD_update() {
- static Etat lastEtat = ETAT_DEMARAGE; // Initialiser avec un état par défaut
- // Mettre à jour l'affichage complet uniquement si l'état a changé
- if (lastEtat != etatActuel) {
- switch (etatActuel) {
- case ETAT_DEMARAGE:
- LCD_Update_DEMARAGE();
- break;
- case ETAT_ORIGINE_INITIALIZATION:
- display.clear();
- display.setCursor(0, 0);
- display.print("Origine");
- display.setCursor(0, 1);
- display.print("Lambda: ");
- break;
- case ETAT_ORIGINE_MAIN:
- LCD_Update_Potard();
- break;
- case ETAT_AVANCE_INITIALIZATION:
- display.clear();
- display.setCursor(0, 0);
- display.print("Avance");
- display.setCursor(0, 1);
- display.print("Lambda: ");
- break;
- case ETAT_AVANCE_MAIN:
- LCD_Update_Steps();
- break;
- case ETAT_TRANSITION_AVANCE_TOGGLE:
- display.clear();
- display.setCursor(0, 0);
- display.print("Toggle");
- display.setCursor(0, 1);
- display.print("Lambda: ");
- break;
- case ETAT_TOGGLE_MAIN:
- LCD_Update_Steps();
- break;
- case ETAT_FAIL:
- LCD_Update_FAIL();
- break;
- default:
- display.clear();
- display.setCursor(0, 0);
- display.print("Etat: ");
- display.print(etatActuel);
- break;
- }
- lastEtat = etatActuel;
- display.display();
- setTaskInterval(LCD_update, INTERVAL_MS_500);
- LCD_interval = INTERVAL_MS_500;
- }else{
- LCD_interval = INTERVAL_MS_3 + LCD_interval;
- if(LCD_interval <= INTERVAL_S_1 ){
- setTaskInterval(LCD_update, LCD_interval);
- }else{
- setTaskInterval(LCD_update, INTERVAL_S_1); //
- }
- }
- // Appeler les mises à jour spécifiques pour les états MAIN
- switch (etatActuel) {
- case ETAT_ORIGINE_MAIN:
- LCD_Update_Potard();
- break;
- case ETAT_AVANCE_MAIN:
- LCD_Update_Steps();
- break;
- case ETAT_TOGGLE_MAIN:
- LCD_Update_Steps();
- break;
- default:
- // Pas de mise à jour spécifique nécessaire
- break;
- }
- } // Fin de LCD_update
- void setup() {
- cli(); // Désactive les interruptions globales pour la configuration initiale
- Serial.begin(115200); // Démarre la communication série à 115200 bps
- display.begin(16, 2); // Initialise l'écran LCD avec 16 colonnes et 2 lignes
- display.setRGB(VAL_RGB_R, VAL_RGB_G, VAL_RGB_B); // Définit la couleur de rétroéclairage de l'écran LCD
- display.print("initialization"); // Affiche le message d'initialisation sur l'écran LCD
- // Configuration des pins pour les LEDs et les sorties
- pinMode(PIN_LED_ORANGE, OUTPUT); // Config. la LED orange en sortie
- pinMode(PIN_LED_VERT, OUTPUT); // Config. la LED verte en sortie
- pinMode(PIN_LED_ROUGE, OUTPUT); // Config. la LED rouge en sortie
- // Configuration des pins pour les entrées
- pinMode(PIN_PWM_IN, INPUT); // Définit le pin A7 comme entrée pour la temperature
- pinMode(PIN_POTARD, INPUT); // Définit le pin A0 comme entrée pour le potentiomètre
- pinMode(PIN_SWITCH, INPUT_PULLUP); // Active la résistance de pull-up sur le pin du bouton
- pinMode(PIN_MOTEUR_DIR, OUTPUT); // Config. la direction du moteur en sortie
- pinMode(PIN_MOTEUR_PUL, OUTPUT); // Config. le pin de pulsation du moteur en sortie
- pinMode(PIN_MOTEUR_ENA, OUTPUT); // Config. le pin d'activation du moteur en sortie
- pinMode(PIN_BUZZER, OUTPUT); // Config. le pin du buzzer en sortie
- pinMode(PIN_PWM_OUT, OUTPUT); // Config. le pin
- pinMode(PIN_COURANT_COUPURE, INPUT_PULLUP); // Active la résistance de pull-up pour la coupure de courant
- // Configuration initiale de l'état des sorties
- digitalWrite(PIN_BUZZER, LOW); // Éteint le buzzer
- digitalWrite(PIN_SWITCH, HIGH); // Initialise le PIN_SWITCH à l'état haut
- digitalWrite(PIN_LED_VERT, HIGH); // Allume la LED verte
- digitalWrite(PIN_LED_ORANGE, HIGH); // Allume la LED orange
- digitalWrite(PIN_LED_ROUGE, HIGH); // Allume la LED rouge
- // Signal sonore d'initialisation
- tone(PIN_BUZZER, NOTE_DS6, 500); // Joue un ton sur le buzzer
- delay(500); // Attend 500 ms
- // Éteint toutes les LEDs après le signal sonore
- digitalWrite(PIN_LED_VERT, LOW); // Éteint la LED verte
- digitalWrite(PIN_LED_ROUGE, LOW); // Éteint la LED rouge
- digitalWrite(PIN_LED_ORANGE, LOW); // Éteint la LED orange
- // Vérifie et récupère l'état de coupure de courant depuis l'EEPROM
- bool spin = false;
- //EEPROM.get(4, spin); // Récupère l'état de coupure de courant de l'EEPROM
- estCoupureCourant = spin;
- // Configuration de l'état initial du programme
- etatActuel = (!estCoupureCourant) ? ETAT_DEMARAGE : ETAT_TOGGLE_RECUPERATION;
- // Configuration du Timer3
- TCCR3A = _BV(COM3A1) | _BV(WGM31); // Fast PWM, 10-bit
- TCCR3B = _BV(WGM33) | _BV(WGM32) | _BV(CS31); // Prescaler = 8
- ICR3 = 0x03FF; // Valeur TOP pour un PWM 10-bit
- // Configuration initiale du Timer4
- // Arrêter le Timer4
- TCCR4A = 0;
- TCCR4B = 0;
- TCNT4 = 0;
- // Configuration du Timer4 en mode Fast PWM, 8 bits
- TCCR4A = _BV(COM4B1) | _BV(WGM41); // Clear OC4B on compare match, Fast PWM
- TCCR4B = _BV(WGM43) | _BV(WGM42) | _BV(CS40); // Fast PWM, prescaler = 1
- ICR4 = 0xFF; // Valeur TOP pour un PWM 8 bits
- // Calculer la nouvelle valeur de comparaison (ICR4) pour générer un PWM avec l'intervalle toutes les INTERVAL_BASE microsecondes
- ICR4 = (16 * INTERVAL_BASE) - 1;
- // Fixer le duty cycle à 50%
- OCR4B = ICR4 / 2;
- // Activer l'interruption de débordement du Timer4
- TIMSK4 |= _BV(TOIE4);
- // Configuration des interruptions
- attachInterrupt(digitalPinToInterrupt(PIN_COURANT_COUPURE), interruptionCoupure, FALLING); // Interruption sur coupure de courant
- // Initial state configuration
- updatePotard(); // Initialise le potentiomètre
- updateSwitchState(); // Initialization de l'état de l'interupteur
- // Actions spécifiques en cas de coupure de courant
- if (estCoupureCourant){
- activateTask(checketatSwitch);
- activateTask(toggleBuzzer);
- }else{
- ledPIN_LED = PIN_LED_ORANGE;
- activateTask(modulate_PIN_LED);
- }
- delay(800); // Court délai avant d'activer les interruptions et les tâches initiales
- // Activation des tâches initiales
- activateTask(LCD_update);
- activateTask(updateSwitchState);
- // Configuration du watchdog timer
- wdt_enable(WDTO_500MS); // Configure the watchdog to timeout after 500 ms
- sei(); // Active les interruptions globales
- }
- void loop() {
- wdt_reset(); // Reset the watchdog timer regularly
- //updateSwitchState(); // est activé en permanance dans executeTaskQueue
- //LCD_Update(); // est activé en permanance dans executeTaskQueue
- switch (etatActuel) {
- case ETAT_DEMARAGE:
- //modulate_PIN_LED(PIN_LED_ORANGE);
- if(!etatSwitch) {
- etatActuel = ETAT_ORIGINE_INITIALIZATION;
- }
- break;
- case ETAT_ORIGINE_INITIALIZATION:
- // Initialisations pour l'état d'origine
- deactivateTask(toggleBuzzer);
- deactivateTask(modulate_PIN_LED);
- activateTask(updatePotard);
- digitalWrite(PIN_LED_ORANGE, LOW); // Éteint la LED orange
- digitalWrite(PIN_LED_ROUGE, HIGH); // Allume la LED rouge
- ledPIN_LED = PIN_LED_VERT;
- activateTask(modulate_PIN_LED);
- digitalWrite(PIN_MOTEUR_ENA, HIGH); // Désactive le frein du moteur
- tone(PIN_BUZZER, NOTE_CS6, 80); // Joue la note CS6
- delay(100); // Pause de 100ms
- tone(PIN_BUZZER, NOTE_DS6, 80); // Joue la note DS6
- delay(100); // Pause de 100ms
- tone(PIN_BUZZER, NOTE_DS6, 160); // Joue la note DS6 plus longue
- delay(250); // Pause de 250ms
- digitalWrite(PIN_LED_ROUGE, LOW); // Éteint la LED rouge
- etatActuel = ETAT_ORIGINE_MAIN; // Définit l'état à ORIGINE
- break;
- case ETAT_ORIGINE_MAIN:
- if(etatSwitch) {
- etatActuel = ETAT_AVANCE_INITIALIZATION;
- }
- break;
- case ETAT_AVANCE_INITIALIZATION:
- // Initialisations pour l'état d'avance
- deactivateTask(updatePotard);
- deactivateTask(modulate_PIN_LED);
- estCoupureCourant = true; // Réinitialise l'indicateur de coupure de courant
- direction = false;
- digitalWrite(PIN_MOTEUR_DIR, LOW); // Définit le sens de rotation du moteur
- digitalWrite(PIN_MOTEUR_ENA, LOW); // Active le moteur
- setTimer4Interval(static_cast<uint32_t>(potard));
- enableTimer4(); // mise en marche du moteur
- digitalWrite(PIN_LED_VERT, HIGH); // Allume la LED verte
- digitalWrite(PIN_LED_ORANGE, LOW); // Éteint la LED orange
- digitalWrite(PIN_LED_ROUGE, LOW); // Éteint la LED rouge
- etatActuel = ETAT_AVANCE_MAIN; // Définit l'état à AVANCE
- break;
- case ETAT_AVANCE_MAIN:
- //Verifie si le programme doit s'arreter en urgence
- checketatFail();
- if(nombreDePas >= LIMITEPASMAX || !etatSwitch) {
- etatActuel = ETAT_TRANSITION_AVANCE_TOGGLE;
- }
- break;
- case ETAT_TRANSITION_AVANCE_TOGGLE:
- // Vérifie la condition de sortie de l'état d'avance
- digitalWrite(PIN_LED_VERT, LOW); // Éteint la LED verte
- disableTimer4();
- direction = true;
- setTimer4Interval(INTERVAL_BASE);
- digitalWrite(PIN_MOTEUR_DIR, HIGH); // Change le sens de rotation du moteur
- digitalWrite(PIN_MOTEUR_ENA, LOW); // Active le moteur
- enableTimer4(); // mise en marche du moteur
- activateTask(checketatSwitch);
- etatActuel = ETAT_TOGGLE_MAIN; // Définit l'état à TOGGLE
- break;
- case ETAT_TOGGLE_MAIN:
- //Verifie si le programme doit s'arreter en urgence
- checketatFail();
- if(nombreDePas == 0){
- etatActuel = ETAT_TOGGLE_CHECKEXITCONDITION;
- }
- break;
- case ETAT_TOGGLE_CHECKEXITCONDITION:
- // Vérifie la condition de sortie de l'état de toggle
- deactivateTask(checketatSwitch);
- disableTimer4();
- estCoupureCourant = false; // Réinitialise l'indicateur de coupure de courant
- digitalWrite(PIN_LED_ORANGE, LOW); // Éteint la LED orange
- digitalWrite(PIN_LED_VERT, LOW); // Éteint la LED verte
- etatActuel = (etatSwitch) ? ETAT_AVANCE_INITIALIZATION : ETAT_ORIGINE_INITIALIZATION;
- break;
- case ETAT_TOGGLE_RECUPERATION:
- recuperation(); // Appelle la fonction de récupération en cas de coupure
- etatActuel = ETAT_TRANSITION_AVANCE_TOGGLE;
- break;
- case ETAT_FAIL:
- // Exécute la séquence d'arrêt d'urgence
- checketatFail();
- break;
- default: // ETAT_FAIL:
- // Exécute la séquence d'arrêt d'urgence
- etatActuel = ETAT_FAIL;
- break;
- }
- manageTask();
- executeTaskQueue();
- }//Fin de la boucle loop
- /*/ Exécute une fonction à intervalle régulier basé sur un timer
- void checkTimerAndUpdate(uint16_t &previousTime, uint32_t intervalAction, CallbackFunction func) {
- if (micros() - previousTime >= intervalAction ) {
- previousTime = micros(); // Réinitialise le temps précédent
- func(); // Appelle la fonction passée en paramètre
- }
- }// Fin de checkTimerAndUpdate*/
- uint8_t OverSample_to_8bit(){
- uint16_t sum = 0;
- uint16_t add;
- for(uint8_t i = 0; i < 4; i++) {
- add = analogRead(PIN_PWM_IN);
- //add = 65535 - add; // Inverser le signal
- add >>= 2; // Diviser par 4 pour éviter le débordement de sum
- sum += add;
- }
- uint8_t result = (uint8_t)(sum >> 4); // Diviser par 2^4 pour obtenir une moyenne sur 8 bits
- if (result == 0xFF) {
- return 0xFE;
- } else {
- return result;
- }
- }
- void temperature(){
- 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)
- 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
- const uint8_t SEUIL_DEGRER = 4;// Valeur equivalente a un degre pour la valeur convertie 16 bits de l'ADC
- const uint16_t TIMER1_INTERVAL_COUNT = 255;
- static bool run_fonctionnement_normal = false;
- static bool isEmergencyMode = false;
- static uint8_t timer1Count = 0;
- static uint8_t isrCounter = 0;
- static uint8_t ValeurSeuil = OverSample_to_8bit();
- static uint8_t buffer_Temperature[32];
- static uint8_t buffer_Time[32];
- static uint8_t index = 0; // Index pour un tableau circulaire
- static uint32_t incrementalInterval = INTERVAL_MS_3; //
- static uint32_t newInterval = INTERVAL_MS_39 + incrementalInterval;
- uint8_t compteur = 0;
- uint8_t validCount = 0;
- uint8_t temp_ValeurSeuil = 0xFF;
- bool variationcheck = false;
- timer1Count += newInterval / INTERVAL_MS_39; // Mise à jour du compteur avec l'intervalle actuel
- isrCounter += newInterval / INTERVAL_MS_39; // Mise à jour du compteur d'interruptions
- uint8_t adcValue_8bit = OverSample_to_8bit();
- variationcheck = (adcValue_8bit != buffer_Temperature[index]);
- buffer_Temperature[index] = adcValue_8bit;
- buffer_Time[index] = 0;
- if (timer1Count >= TIMER1_INTERVAL_COUNT) {
- timer1Count = 0;
- run_fonctionnement_normal = true;
- }
- for (uint8_t i = 0; i < 32; i++) {
- if (buffer_Temperature[i] == 0xFF && buffer_Time[i] == 0xFF) continue;
- validCount++;
- if (!isEmergencyMode && variationcheck && buffer_Temperature[i] < ValeurSeuil) {
- temp_ValeurSeuil = buffer_Temperature[i];
- } else if (isEmergencyMode && (buffer_Temperature[i] - SEUIL_DEGRER) <= ValeurSeuil) {
- compteur++;
- }
- buffer_Time[i] += (i != index) * isrCounter; // Augmente le temps pour tous sauf l'index actuel
- if (buffer_Time[i] >= 0xFF - isrCounter) {
- buffer_Time[i] = 0xFE;
- buffer_Temperature[i] = 0xFF;
- }
- }
- isrCounter = 0;
- index = (index + 1) % 32; // Incrémente l'index circulairement
- // Ajustement de l'intervalle d'appel de la fonction
- if (isEmergencyMode) {
- newInterval = INTERVAL_MS_39; // Réinitialiser l'intervalle en mode d'urgence
- incrementalInterval = INTERVAL_MS_3; // Réinitialiser l'intervalle incrémental
- if (compteur == validCount) {
- isEmergencyMode = false;
- OCR3A = 0xFF;
- }
- } else {
- if (variationcheck) {
- int32_t difference = abs((int)ValeurSeuil - (int)temp_ValeurSeuil);
- ValeurSeuil = temp_ValeurSeuil;
- uint32_t x = incrementalInterval / INTERVAL_MS_3;
- uint32_t reductionFactor = 1 + (uint32_t)difference; // Plus la différence est grande, plus le facteur de réduction est élevé
- uint32_t y = x / reductionFactor ;
- y = y > 0 ? y : 1; // Assurer que y ne tombe pas en dessous de 1
- uint32_t changeAmount = y * INTERVAL_MS_3;
- incrementalInterval = incrementalInterval - changeAmount; // réduire l'intervalle sur changement de température
- incrementalInterval = incrementalInterval > INTERVAL_MS_3 ? incrementalInterval : INTERVAL_MS_3; // Ne pas tomber sous INTERVAL_MS_3
- }else {
- uint32_t x = incrementalInterval / INTERVAL_MS_3;
- uint32_t y = 2 * (x - 1) + 1; // Appliquer la formule y = 2(x-1) + 1
- incrementalInterval = (y * INTERVAL_MS_3);
- incrementalInterval = incrementalInterval < INTERVAL_S_10 ? incrementalInterval : INTERVAL_S_10; // Limite supérieure à 3182 secondes
- }
- newInterval = INTERVAL_MS_39 + incrementalInterval;
- newInterval = newInterval < INTERVAL_MS_10 ? newInterval : INTERVAL_S_10 ; // Limite supérieure à 10 secondes
- if ((adcValue_8bit - ValeurSeuil) >= SEUIL_URGENCE) {
- isEmergencyMode = true;
- }
- if (run_fonctionnement_normal) {
- static uint8_t duty_actuel = 0;
- if (adcValue_8bit < SEUIL_ARRET) {
- OCR3A = 0;
- } else if (adcValue_8bit != duty_actuel && adcValue_8bit > SEUIL_ARRET) {
- OCR3A = adcValue_8bit;
- duty_actuel = adcValue_8bit;
- }
- run_fonctionnement_normal = false;
- }
- }
- setTaskInterval(temperature, newInterval);
- }//Fin de temperature
- //Fonction de mise à jour de potard et de la fréquence du PWM du moteur
- void updatePotard() {
- uint16_t newPotard = map(analogRead(PIN_POTARD), 0, 1023, 11200, 11300); // Map la lecture analogique à la plage désirée
- if (newPotard != potard) { // Vérifie si la valeur a changé
- potard = newPotard; // Met à jour la variable globale potard
- }
- }// Fin de updatePotard
- // Met à jour l'état de l'interrupteur
- void updateSwitchState() {
- static uint32_t lastChangeTime = 0;
- static uint32_t currentInterval;
- uint32_t currentTime = millis();
- if (digitalRead(PIN_SWITCH) != etatSwitch) { // Vérifie si l'interrupteur à bascule a changé
- etatSwitch = !etatSwitch; // Bascule l'état de l'interrupteur
- // Réinitialise l'intervalle d'appel après un changement d'état
- currentInterval = INTERVAL_MS_20; // Réinitialise l'intervalle à une valeur moyenne
- setTaskInterval(updateSwitchState, currentInterval);
- lastChangeTime = currentTime;
- } else {
- // Ajuste l'intervalle en fonction du temps écoulé depuis le dernier changement d'état
- if (currentTime - lastChangeTime > currentInterval) {
- if (currentInterval < INTERVAL_S_1) {
- currentInterval += INTERVAL_MS_10; // Augmente l'intervalle si l'état n'a pas changé
- currentInterval = min(currentInterval, INTERVAL_S_1); // S'assure de ne pas dépasser l'intervalle max
- }
- setTaskInterval(updateSwitchState, currentInterval);
- } else {
- if (currentInterval > INTERVAL_MS_20) {
- currentInterval -= INTERVAL_MS_10; // Réduit l'intervalle si l'état a changé
- currentInterval = max(currentInterval, INTERVAL_MS_20); // S'assure de ne pas aller en dessous de l'intervalle min
- }
- setTaskInterval(updateSwitchState, currentInterval);
- }
- }
- }// Fin de updateSwitchState
- // Fait varier la luminosité de la LED
- void modulate_PIN_LED() {
- static uint8_t i = 1; // Initialise l'intensité de la LED
- static bool estIncrement = true; // Initialise la direction de l'incrémentation
- analogWrite(ledPIN_LED, i);
- i = estIncrement ? i + 1 : i - 1; // Incrémente ou décrémente la luminosité
- if(i == 255 || i == 0) { // Verifie si i est arrivé au extremiter
- estIncrement = !estIncrement; // Inverse la direction si les limites sont atteintes
- }
- }// Fin de modulate_PIN_LED
- // Fonction pour basculer l'état d'une broche
- void toggle(uint8_t pin) {
- uint8_t port = digitalPinToPort(pin); // Obtenir le port de la broche
- uint8_t bit = digitalPinToBitMask(pin); // Obtenir le bit de la broche
- // Obtenir l'adresse du registre de sortie pour le port
- volatile uint8_t *out = portOutputRegister(port);
- // Bascule l'état de la broche en utilisant XOR
- *out ^= bit;
- } // Fin de toggle
- void toggleLEDVert() {
- toggle(PIN_LED_VERT);
- }
- void toggleLEDOrange() {
- toggle(PIN_LED_ORANGE);
- }
- // Exécute une action LED en fonction de l'état de l'interrupteur
- void checketatSwitch() {
- etatSwitch = digitalRead(PIN_SWITCH); // Lire l'état de l'interrupteur
- uint8_t ledPin = !etatSwitch ? PIN_LED_VERT : PIN_LED_ORANGE; // Déterminer quelle LED vérifier pour l'extinction
- CallbackFunction func = etatSwitch ? toggleLEDVert : toggleLEDOrange; // Déterminer quelle fonction appeler pour basculer l'état de la LED
- if (digitalRead(ledPin) == HIGH) {
- digitalWrite(ledPin, LOW); // Éteindre la LED si elle est allumée
- }
- func(); // Appeler la fonction de basculement de la LED
- }// Fin de checkTimerBasedOnState
- //Actionne le moteur et décompte les pas
- /*void toggle_PIN_MOTOR() {
- toggle(PIN_MOTEUR_PUL); // Bascule le pin du moteur
- noInterrupts(); // Désactive les interruptions
- direction ? nombreDePas-- : nombreDePas++; // Décrémente le compteur de pas
- interrupts(); // Réactive les interruptions
- }// Fin de toggle_PIN_MOTOR*/
- //tone utilise le Timer2
- void toggleBuzzer() {
- static bool isActive = true;
- if (isActive) {
- noTone(PIN_BUZZER); // Arrête le son pendant 84 millisecondes
- isActive = false; //
- } else {
- tone(PIN_BUZZER, NOTE_DS6, 160); // Joue la note DS6 pendant 160 millisecondes
- isActive = true;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement