//------------------------------------------------------------------------------ // *** STROBODUINO *** //------------------------------------------------------------------------------ char Ver[] = "cg230417"; #include // Timer1 --> timer entre étincelle et Flash #include // Bibiliothèque pour gestion encoder avec anti-rebond #include // Lect/Ecrit dans l'EEPROM interne à l'ATMEL pour svg des param. #include // LCD #include // Calcul de moy. glissante pour lisser le compte-tour bool debug = 0; // true si debug //------------------------------------------------------------------------------ // PARAMETRES (stockés dans l'EEPROM) //------------------------------------------------------------------------------ byte D_Flash = 10; // Durée du flash en µs, autour de 10µs byte Ncyl = 2; // Nombre de cylindres byte Refresh = 100; // Refresh du LCD en millisec. //------------------------------------------------------------------------------ // CONSTANTES //------------------------------------------------------------------------------ #define Etin 2 // Entrée bobine #define Inter 5 // Inter du codeur #define Flash 11 // Flash #define Codeur_A 3 // D3 pour entrée codeur A sous interruption #define Codeur_B 4 // D4 pour entrée codeur B const byte lissrpm = 3; // Nb de valeurs pour moy. glissante compte-tours const int deg_Initial = 10; // Affiché au demarrage //------------------------------------------------------------------------------- // VARIABLES //------------------------------------------------------------------------------- volatile long T = 0; // Periode en cours(signée pour le calcul de D_deg) unsigned long prec_H = 0; // Heure du front precedent en µs volatile int deg_dem = deg_Initial; // Compteur des degrés demandés volatile long D_deg = 0; // Délai pour deg_dem degrès en µs unsigned long N = 0; // N en tours/mn unsigned long Nc = 0; // Pour le calcul de N unsigned long pm = 0; // Previous millis pour Refresh LCD byte modconfig = 0; // Flag pour savoir si on est en mode config int degT = 720 / Ncyl; // Degrés entre 2 étincelles LiquidCrystal lcd( 9, 17, 15, 16, 14, 10); //lcd(RS, E, D4, D5, D6, D7) Encoder Enco(Codeur_A, Codeur_B); RunningAverage RArpm(lissrpm); //-------------------------------------------------------------------------------- // ISR //-------------------------------------------------------------------------------- void isrEtincelle() { T = micros() - prec_H; // Calcul de T prec_H = micros(); Timer1.initialize(D_deg); // Flash après delai D_deg µs } void isrFlash(){ Timer1.stop(); //Flash et flash sur LED13 digitalWrite (Flash, 1); delayMicroseconds(D_Flash); digitalWrite (Flash, 0); digitalWrite (LED_BUILTIN, 1); delayMicroseconds(10 * D_Flash); digitalWrite (LED_BUILTIN, 0); //Délai en µs pour les degrés demandés, periode suivante D_deg = float(T * deg_dem) / float(degT); // Si retard demandé, on ajoute un tour if (deg_dem < 0){D_deg += float(T * 360) / float(degT);} // On ajoute la valeur de T au calcul de moy. glissante RArpm.addValue(T); // DEBUG //if (debug) {Serial.print("T : "); Serial.print(T); Serial.print(" D_deg : "); Serial.println(D_deg);} //if (debug) {Serial.print("degT : "); Serial.print(degT); Serial.print(" deg_dem : "); Serial.println(deg_dem);} } //-------------------------------------------------------------------------------- // FONCTIONS //-------------------------------------------------------------------------------- void Affic_N_et_deg_dem(){ // Affiche compte-tour et dégrés demandés N = Nc / RArpm.getAverage(); // Calculer N en t/mn lcd.setCursor(0, 0); lcd.print(" "); lcd.setCursor(0, 0); lcd.print(N); // Régime tr/min lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(deg_dem); lcd.write(223); // Avance ° } void Affich_fond_ecran(){ // Affiche le fond d'écran au début ou après la config. lcd.clear(); lcd.setCursor(5, 0); lcd.print("tpm"); lcd.setCursor(5, 1); lcd.print(Ncyl); lcd.print("c"); } void Regl(byte &var, String titre){ // Macro de réglage pour param type byte lcd.clear(); lcd.print(titre); Enco.write(var*4); // Init l'encodeur avec la valeur actuelle while (digitalRead(Inter) == 1){ // tant qu'on appuie pas on régle var = Enco.read()/4; lcd.setCursor(3, 1); lcd.print(var); // Affiche la valeur lcd.print(" "); } while (digitalRead(Inter) == 0); // Si on a appuyé, on attend le relachement } void Regl(bool &var, String titre){ // Macro de réglage pour param type bool lcd.clear(); lcd.print(titre); lcd.setCursor(3, 1); lcd.print(var); lcd.print(" "); long flag = 0; Enco.write(0); while (digitalRead(Inter) == 1){ // tant qu'on appuie pas on régle if (flag != Enco.read()/4) { var = !var; flag = Enco.read()/4; lcd.setCursor(3, 1); lcd.print(var); lcd.print(" "); } } while (digitalRead(Inter) == 0); // Si on a appuyé, on attend le relachement } void ConfiG() { modconfig=0; lcd.clear(); lcd.print("CONFIG"); lcd.setCursor(7, 1); lcd.write(126); while (digitalRead(Inter) == 0); //toujours appuyé ? on attend // Réglages avec le codeur Regl(Ncyl, "Nb cyl."); Regl(D_Flash, "D Flash"); Regl(Refresh, "Refresh"); // Sauvegarde des paramètres dans l'EEPROM EEPROM.write(0, Ncyl); EEPROM.write(1, D_Flash); EEPROM.write(2, Refresh); IniT(); } //------------------------------------------------------------------------------ // SETUP //------------------------------------------------------------------------------ void IniT() { // On charge les paramètres stockés en mémoire Ncyl = EEPROM.read(0); D_Flash = EEPROM.read(1); Refresh = EEPROM.read(2); // Interruption détection d'étincelle attachInterrupt(digitalPinToInterrupt(Etin), isrEtincelle, RISING); // Timer entre Etincelle et Flash Timer1.attachInterrupt(isrFlash); Timer1.stop(); modconfig=0; // Affichage titre lcd.clear(); lcd.print("Strobo"); lcd.setCursor(3, 1); lcd.print("duino"); delay(1200); // Bouton appuyé if (digitalRead(Inter) == 0) {modconfig++;} // Test Flash digitalWrite (Flash, 1); delayMicroseconds(D_Flash); digitalWrite (Flash, 0); lcd.clear(); lcd.print("Version"); // Affichage version lcd.setCursor(0, 1); lcd.print(Ver); // N° de version delay(1000); if (digitalRead(Inter) == 0) {modconfig++;} // si bouton toujours appuyé if (modconfig >= 2) {ConfiG();} // on entre dans le mode config Enco.write(deg_Initial*4); degT = 720 / Ncyl; Nc = 120000000 / Ncyl; T = 150000; RArpm.addValue(T); D_deg = float(T * deg_dem) / float(degT); // Pour le premier cycle Affich_fond_ecran(); Affic_N_et_deg_dem(); } void setup() { if (debug) {Serial.begin(9600);} // Pour debug pinMode(Etin, INPUT); // Entrée bobine pinMode(Flash, OUTPUT); // Sortie FLASH pinMode(Codeur_A, INPUT_PULLUP); pinMode(Codeur_B, INPUT_PULLUP); pinMode(Inter, INPUT_PULLUP); // Le codeur met son inter à la masse quand poussé lcd.begin(8, 2); // LCD 8 colonnes, 2 lignes IniT(); } //------------------------------------------------------------------------------ // LOOP //------------------------------------------------------------------------------ void loop(){ if ((millis() - pm) > Refresh) { // Mise à jour affichage LCD Affic_N_et_deg_dem(); // Affichage tr/min et deg_demandés pm = millis(); deg_dem = Enco.read()/4; // On lit les degrés demandés via l'encodeur } if (digitalRead(Inter) == 0) { // Si l'inter du codeur est poussé, geler l'affichage delay(1000); while (digitalRead(Inter) == 0); // Encore poussé, attendre delay(100); // Continuer } }