Arduino 12
Gestion d'un menu général
Sommaire
| 'Mode' ou gestion d'un menu général |
Cette version représente un grand pas vers notre 'squelette universel'. Avec un LCD et un clavier, on va élaborer un 'MENU GENERAL' qui va permettre de choisir un 'MODE DE FONCTIONNEMENT' particulier.
On définit d'abord les libellés des fonctions par cette déclaration :
// definition des modes de fonctionnement correspondant aux différentes fonctions possibles
char* modex[]={"Horl","Freq", "Self", "Capa", "Volt", "GBF_","PWM_","Srvo","Acco","Baro","Ther","Reve","Cafe","Mors", " ", " "," -- ++ Ok Ok "};
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
#define modemax 13
int mode=0,modeav=modemax,modeap=1;
Notez que la position 15 est un message-guide utilisé ensuite dans la présentation LCD.
On va afficher sur le LCD 3 fonctions contigües, la centrale étant entourée de <>, les touches 3 et 4 permettant de se déplacer dans les options (-- et ++), toutes les autres touches étant 'OK' et validant le choix.
On devrait donc avoir sur le LCD le menu général : | |  |
La gestion de ce menu général est réalisée par les étapes 10 et 11 du 'grafcet_a'. On démarre d'ailleurs avec grafcet_a=10 :
//--------------------------------
// mode par défaut, attente de choix d'un mode
case 10:
// affichage menu déroulant horizontal
modeav = ((modeɬ)?mode-1:modemax); // option précédente
modeap = ((mode<modemax)?mode+1:0); // option suivante
// ou plus simplement (mais 4 octets de plus !!!) : if (mode < modemax ) { modeap = mode+1; } else { modeap = 0; }
// affichage de la 1ère ligne du LCD
lcd.setCursor(0, 0); lcd << modex[modeav] << " <" << modex[mode] << "> " << modex[modeap] ;
// affichage de la 2ème ligne du LCD
lcd.setCursor(0, 1); lcd << modex[16];
// passage à l'étape suivante
grafcet_a++;
// on arme la 'tempo_a', si on n'a pas choisi avant la fin des 15 secondes, on passe en 'Horl'oge
tempo_a = 15000; // on arme la tempo, si on n'a pas choisi avant la fin, on passe en horloge
break;
// attente appuis sur les touches
case 11:
// time-out : retour à l'horloge en fin de tempo
if (tempo_a == 0) { grafcet_a = 0; }
// touche 3='--' sans répétition
if (touche == '3') {
mode = modeav;
grafcet_a = 10;
touche = ' ';
}
// touche 4='++' avec répétition
if (touche_repeat == '4') {
mode = modeap;
grafcet_a = 10;
touche_repeat = ' ';
}
// toutes les autres touches = Ok
// 3 est automatiquement exclue du fait qu'elle est traitée avant (alors touche =' '),
// mais pour la touche '4' il faut rajouter le test, car elle est gérée avec répétition !
if (touche != ' ' and touche != '4') {
// quand on valide, on va sauter à une étape de grafcet correpondant à la fonction désirée,
// on a choisi comme première étape mode*100. Donc, par exemple, pour 'Capa' mode=3 on saute en 'grafcet_a=300'
grafcet_a = 100*mode;
tempo_a = 0;
// debug lcd.setCursor(0, 1); lcd << "mod=" << mode << " gr=" << grafcet_a; delay(1000);
Serial << modex[mode] << endl;
// Notez que l'on nettoie le LCD, pour laisser l'affichage à la fonction choisie ...
lcd.clear(); touche_repeat = ' '; touche = ' ';
}
break;
A noter également un sous-programme de formatage de valeurs 'float' :
void affiche_valeur(float v,char unite,int nbchiffres) //,char* sortie)
v = valeur en entrée
unite = unité en 1 caractère : V pour Volt, F pour Farad, c pour cycle/seconde (Hertz=Hz) ...
nbchiffres = nombre de chiffres significatifs
Le multiplicateur est automatiquement mis en place, les valeurs étant comprises entre 0. et 999. . Par exemples :
affiche_valeur(123.456789012345,'V',4) = '123.4 V'
affiche_valeur(1234.56789012345,'V',7) = '1.234567kV'
affiche_valeur(0.0000000001,'F',4) = '100.0pF'
affiche_valeur(0.000022,'F',4) = '22.00uF'
affiche_valeur(123456789.012345,'c',6) = '123.456Mc'
affiche_valeur(123456789012345.,'o',9) = '123.456789To'
| Voici (enfin !) les premières fonctions ... fonctionnelles ! |
Après le menu général, on va décrire quelques fonctions simples pour démarrer. Ensuite on fera sans doute moins de commentaires, et il faudra bien revenir à une description HARDWARE complète et une NOTICE UTILISATEUR !.
Donc : mode=0 --> grafcet_a = 0
Cette fonction, très simpliste, consiste à afficher l'heure et la date. Voir étape 0, triviale ! ...
L'affichage du nom du jour a été traité par :
char* jours[] = {"Sam","Dim","Lun","Mar","Mer","Jeu","Ven"} ;
Notez que cette horloge est très bête : elle est initialisée à n'importe quoi, enfin par :
// mise à l'heure
setTime(12,15,00,26,02,13); // 12h15 le 25 déc 2013
et n'est pas synchronisée (développements à suivre). Remarquez l'affichage de la date sur les secondes 8 et 9 de chaque dizaine.
Un appui sur une touche quelconque permet de repasser au menu général en étape 10.
| Fonctions Frequencemetre Selfmetre Capacimetre |
SIMULATION SEULEMENT !
Ces 3 fonctions ne sont là que pour montrer comment ajouter de nouvelles fonctionnalités. Elles simulent des affichages, mais devraient être ceux des fonctions développées ensuite (il va falloir retourneer à construire des interfaces ...).
Remarquez que si vous choisissez une fonction inexistante, dans le menu général, on retourne au menu général immédiatement (même pas de message !)
FONCTIONNEL !
Afin de tester ce mode, il faut avoir un haut parleur. Relier un petit HP ou un transducteur piezo à la sortie 3 de l'ARDUINO, avec un résistance en série de 220 à 2200 Ohms (selon volume désiré). La sortie est initialisée par :
pinMode(sortie_gbf, OUTPUT);
Ce Générateur Basse Fréquences va générer un signal sur la broche 3, dont la fréquence va être réglable au clavier.
Regardez les étapes 500 à 502 :
//--------------------------------
// GBF
// INITIALISATION à 880 Hertz (c'est un 'LA' double du diapason)
case 500:
freq=880.000; // Hertz
grafcet_a++; // et on passe à l'étape suivante
break;
// génération du son
case 501:
// limites
if (freq < 1.) freq=1.;
if (freq > 50000.) freq=50000.;
// affichage menu et fréquence actuelle
lcd.setCursor(0, 1); lcd << " -- - + ++ ";
lcd.setCursor(0, 0); lcd << modex[mode] << " F=";
Serial << modex[mode] << " F=";
affiche_valeur(freq,'c',5);
// GBF effectif
tone(sortie_gbf, (unsigned int) freq );
// pour scrutation clavier
tempo_a = 100;
grafcet_a++; // et on passe à l'étape suivante
break;
// gestion clavier
case 502:
// retour au menu général
if (touche == '0') {
noTone(sortie_gbf); // stop GBF
touche = ' ';
grafcet_a=9999; // pour raz grafcet
}
// valeurs calibrées
if (touche == '1') freq = 440.;
if (touche == '2') freq = 880.;
// descente d'une demi-gamme
if (touche == '3') freq /= racine2;
// descente d'un demi-ton
if (touche_repeat == '4') { freq /= demiton; touche_repeat = ' '; }
// montée d'un demi-ton
if (touche_repeat == '5') { freq *= demiton; touche_repeat = ' '; }
// montée d'une demi-gamme
if (touche == '6') freq *= racine2;
// valeurs calibrées
if (touche == '7') freq = 1760.;
if (touche == '8') freq = 3520.;
if (touche == '9') freq = 7040.;
if (touche != ' ') { grafcet_a--; touche = ' '; } // raz touche appuyée
if (tempo_a == 0) grafcet_a--;
break;
POUR BIDOUILLE (fonction ne risquant rien, ou pouvant servir de modèle pour la suite)
//--------------------------------
// Café (en fait, bidouille)
case 1200:
i=0;
grafcet_b=1;
grafcet_a++;
break;
case 1201:
// chenillard
lcd.setCursor(i, 0); lcd << " ";
i++; if (iᡇ) i=0;
lcd.setCursor(i, 0); lcd << "*";
// affichage des états des 2 grafcets
lcd.setCursor(0, 1); lcd << grafcet_a << "ab" << grafcet_b << " ";
// et de la vitesse de l4ARDUINO
lcd.setCursor(11, 1); lcd << tours_ps << " ";
tempo_a = 100; // on arme la tempo
grafcet_a++;
break;
case 1202:
if (touche == '0') {
touche = ' ';
grafcet_b=0;
grafcet_a=9999; // pour raz grafcet
}
if (tempo_a == 0) grafcet_a=1201;
break;
/*
GoodFields 12_mode
GBF
Fréquencemètre, capacimètre, selfmètre : simulés
---
Modes et menu général
Clavier analogique à diodes et debug
LCD
Gestion du temps
Compactage des sorties série (intégration d'une bibliothèque : Streaming)
GRAFCET
TEMPORISATION basique
FRONT MONTANT/DESCENDANT
*/
//**********************************************************
// BIBLIOTHEQUES
// incluses dans le package Arduino de base
#include <LiquidCrystal.h> // LCD
// ajoutées
#include <Streaming.h>
#include <Time.h>
// DEBUG : 0=pas de debug, valeur selon besoins
#define debug 0
//**********************************************************
// DECLARATIONS
// LCD initialize the library with the numbers of the interface pins
/* Câblage du LCD
* LCD pin 1 to GND
* LCD pin 2 to VCC 5V
* LCD pin 3 : contraste sur le point milieu d'un potentiomètre de 10K entre le GND et le VCC (réglé très près de la masse)
* LCD pin 4 RS to digital pin 4
* LCD pin 5 RW to GND
* LCD pin 6 Enable pin to digital pin 2
* LCD pin 11 D4 pin to digital pin 6
* LCD pin 12 D5 pin to digital pin 7
* LCD pin 13 D6 pin to digital pin 8
* LCD pin 14 D7 pin to digital pin 9
*/
// LiquidCrystal lcd(RS, Enable, D4, D5, D6, D7)
LiquidCrystal lcd(4, 2, 6, 7, 8, 9);
// entrées-sorties
#define led_a 13
#define sortie_gbf 3
// temporisations
int tempo_a,tempo_b;
// vitesse de clignotement : maintenant en millisecondes
int tempo_a_reset=1000;
int tempo_b_reset=700;
// gestion du temps
int previousSecond; // secondes de l'horloge
int top_dixieme=false; // top pour traitements au 1/10 seconde dans le P/P
int top_seconde=false; // top pour traitements à la seconde dans le P/P
int top_minute=false; // top pour traitements à la minute dans le P/P
unsigned long previousMillis, previousDecis;
char* jours[] = {"Sam","Dim","Lun","Mar","Mer","Jeu","Ven"} ;
// clavier à 16 touches et diodes sur entrée analogique
int clavier=A0;
int itouche,itouche1=-1,itouche2=-1,vtouche,ntouche,tempo_repeat;
// touche renvoyée
char touche=' ',touche_repeat=' ';
// CLAVIER 10 TOUCHES A DIODES 0,2V
int nbtouche = 10;
// caractère touche renvoyée
// <----------------clavier-10 touches------------> 16 touches---> 24 touches--->
char ltouche[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' '}; // nbtouche
// valeurs analogiques. A ajuster selon valeurs relevées après montage # 41 pour 0,2 Volts/diode
int xtouche[] = { 0, 45, 90, 136, 181, 226, 270, 313, 354, 396, 437, 1023}; // nbtouche+1
/*
// CLAVIER 24 TOUCHES A DIODES 0,2V
int nbtouche = 24;
// caractère touche renvoyée
// <----------------clavier-10 touches------------> 16 touches---> 24 touches--->
char ltouche[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', ' '}; // nbtouche
// valeurs analogiques. A ajuster selon valeurs relevées après montage # 41 pour 0,2 Volts/diode
int xtouche[] = { 0, 45, 91, 136, 181, 226, 270, 313, 354, 396, 437, 478, 519, 560, 601, 642, 683, 724, 765, 806, 847, 888, 929, 970, 1010, 1023}; // nbtouche+1
*/
// speedomètre = calcul de vitesse ...
unsigned int tours_ps,tours,tours_led;
// GRAFCETS
int grafcet_a=0,grafcet_b=0;
// definition des modes de fonctionnement correspondant aux différentes fonctions possibles
char* modex[]={"Horl","Freq", "Self", "Capa", "Volt", "GBF_","PWM_","Srvo","Acco","Baro","Ther","Reve","Cafe","Mors", " ", " "," -- ++ Ok Ok "};
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
#define modemax 13
int mode=0,modeav=modemax,modeap=1;
// variables très locales !
int i;
//int j;
// Constantes sympas
float deuxpi=6.283185307; // 179586476925286766559; // à peu près 2 Pi
float racine2 = 1.414213562; //3730950488016887242097; // racine carree de 2
float demiton = 1.059463094; //3592952645618252949463; // 2 puissance 1/12
// FREQUENCES, CAPAS, SELFS
float self,capa,freq;
//**********************************************************
// INITIALISATIONS
void setup() {
// initialize the pins
pinMode(led_a, OUTPUT);
pinMode(sortie_gbf, OUTPUT);
pinMode(clavier, INPUT);
digitalWrite(clavier, HIGH); // turn on pullup resistors
// définition taille du LCD :
lcd.begin(16, 2);
// mise à l'heure
setTime(12,15,00,26,02,13); // 12h15 le 25 déc 2013
// ligne série (pour traces)
Serial.begin(9600); // ou 9600 selon votre port COM
#if debug > 0
Serial << "Serial ok" << endl;
#endif
// AFFICHAGE sur LCD
lcd.setCursor(0, 0); lcd << "Serial OK"; // 1ere ligne
lcd.setCursor(0, 1); lcd << "GoodFields"; // 2eme ligne lcd.print ("toto="); lcd.pprint (toto,2);
delay(500); // pour profiter du LCD au démarrage
lcd.clear(); // Effacement général LCD
} // Fin du SETUP
//**********************************************************
// PROGRAMME PRINCIPAL
void loop() {
// compte-tours par seconde et led_a "heart-beat" commutée
if (tours < 65535) tours++;
tours_led++;
if (tours_led > 10000) { tours_led = 0 ; digitalWrite(led_a, !digitalRead(led_a)); }
// gestion du temps (dont temporisations)
ger_top_centieme ();
// opérations à chaque dixième de seconde
if (top_dixieme) {
top_dixieme = false;
}
// opérations à chaque seconde
if (top_seconde) {
top_seconde = false;
tours_ps=tours; tours=0;
}
//********************************************************************************
switch (grafcet_a) {
/* MODES : on arme le grafcet à mode*100
mode - fonction
0 - horloge basique
1 - fréquencemètre (8 Mhz à priori, c'est facile le selfmètre capacimètre en est un)
2 - un selfmètre capacimètre (c'est l'idée de départ) ???
3 - capacimètre
4 - un quadri-voltmètre 20 Volts, ampèremètre éventuel (détecteur à faire, mais je connais l'astuce) ???
5 - un GBF (ce que peut faire l'Arduino, sans doute jusque vers 30 kHz) ???
6 - mais aussi générateur de signal pour tester des servo moteurs de télécommande ???
7 - et encore générateur de commande PWM ???
8 - un accordeur de guitare ou autre bombarde (quand j'aurais connecté un HP) ???
9 - un baro-thermomètre à base de BMP085 (bus I2C sur A4+A5) ???
10 - un appareil de mesure de capacité isolante d'un mur (avec 3 capteurs DS1820 bus 1 fil sur A5) ???
11 - horloge réveil temporisation ( synchro avec horloge temps réel DS1307 ou horloge radio DFM77 ??? )
12 - pas le café, quoi que ...
- une alimentation 5V et 12 V pour bidouiller
*/
//--------------------------------
// mode horloge basique
case 0:
// appel menu général
if (touche != ' ') {
grafcet_a = 10;
touche = ' ';
}
// horloge de base
if (tempo_a == 0) {
tempo_a = 1000;
horodatage_serial(); Serial << " top" << tours_ps << "t/s " << grafcet_a << " " << grafcet_b << endl;
lcd.setCursor(0, 0);
if (second()%10 > 7) {
lcd << " " << jours[weekday()] << " " << ((day())?"0":"") << day() << "/" << ((month())?"0":"") << month() << "/" << year() << " " ;
} else {
lcd << " " << ((hour())?"0":"") << hour() << ":" << ((minute())?"0":"") << minute() << ":" << ((second())?"0":"") << second() << " GER";
}
}
break;
//--------------------------------
// mode par défaut, attente de choix d'un mode
case 10:
// affichage menu déroulant horizontal
modeav = ((modeɬ)?mode-1:modemax);
modeap = ((mode<modemax)?mode+1:0);
// ou plus simplement (mais 4 octets de plus !!!) : if (mode < modemax ) { modeap = mode+1; } else { modeap = 0; }
lcd.setCursor(0, 0); lcd << modex[modeav] << " <" << modex[mode] << "> " << modex[modeap] ;
lcd.setCursor(0, 1); lcd << modex[16];
grafcet_a++;
tempo_a = 15000; // on arme la tempo, si on n'a pas choisi avant la fin, on passe en horloge
break;
case 11:
// retour à l'horloge
if (tempo_a == 0) { grafcet_a = 0; }
// - sans répétition
if (touche == '3') {
mode = modeav;
grafcet_a = 10;
touche = ' ';
}
// + avec répétition
if (touche_repeat == '4') {
mode = modeap;
grafcet_a = 10;
touche_repeat = ' ';
}
// Ok
if (touche != ' ' and touche != '4') { // 3 est exclue du fait que traitée avant !
grafcet_a = 100*mode;
tempo_a = 0;
// debug lcd.setCursor(0, 1); lcd << "mod=" << mode << " gr=" << grafcet_a; delay(1000);
Serial << modex[mode] << endl;
lcd.clear(); touche_repeat = ' '; touche = ' ';
}
break;
//--------------------------------
// Frequencemetre
case 100:
grafcet_a++; // et on passe à l'étape suivante
freq = 144612500.;
break;
case 101:
freq += 0.001*millis();
lcd.setCursor(0, 0); lcd << modex[mode] << "="; Serial << modex[mode] << "=";
affiche_valeur(freq,'c',7);
Serial << endl;
tempo_a = 1000; // on arme la tempo
grafcet_a++; // et on passe à l'étape suivante
break;
case 102:
if (touche == '0') {
touche = ' ';
grafcet_a=9999; // pour raz grafcet
}
if (tempo_a == 0) grafcet_a=101;
break;
//--------------------------------
// Selfmetre - Capacimètre
case 200:
case 300:
self=0.000068; // 68 uH
capa=0.000000000680; // 680 pF
grafcet_a++; // et on passe à l'étape suivante
// self = self0; capa = capa0; // pour simulation
break;
case 201:
case 301:
lcd.setCursor(0, 0); lcd << modex[mode] << "=" ;
Serial << modex[mode] << " " ;
// Capacimètre
if (grafcet_a > 250) {
// x = 1. / (self * pow(deuxpi * freq, 2.)); // C = 1 / (L * (2 * Pi * F)²)
// capa = x-capa0;
capa *= 1.41421356;
affiche_valeur(capa,'F',4);
Serial << " " ;
lcd.setCursor(0, 1);
affiche_valeur(self,'H',4);
// Selfmetre
} else {
// x = 1. / (capa * pow(deuxpi * freq, 2.)); // L = 1 / (C * (2 * Pi * F)²)
// self = x-self0;
self *= 1.41421356;
affiche_valeur(self,'H',4);
Serial << " " ;
lcd.setCursor(0, 1);
affiche_valeur(capa,'F',4);
}
Serial << " " ;
lcd << " ";
// calcule la fréquence de résonnance
freq = 1. / (deuxpi * pow(self*capa,0.5)); // F = 1 / (2 * Pi * racine_carree ( L * C ))
affiche_valeur(freq,'c',5);
Serial << endl;
tempo_a = 2500; // on arme la tempo
grafcet_a++; // et on passe à l'étape suivante
if (capa > 0.000000680 or self > 0.068 ) grafcet_a-=2;
break;
case 202:
case 302:
if (touche == '0') {
touche = ' ';
grafcet_a=9999; // pour raz grafcet
}
if (touche == '1') {
self=0.01-self;
capa=0.0000001-capa;
grafcet_a--;
touche = ' ';
}
if (tempo_a == 0) grafcet_a--;
break;
//--------------------------------
// GBF
// INITIALISATION à 880 Hertz (c'est un 'LA' double du diapason)
case 500:
freq=880.000; // Hertz
grafcet_a++; // et on passe à l'étape suivante
break;
// génération du son
case 501:
// limites
if (freq < 1.) freq=1.;
if (freq > 50000.) freq=50000.;
// affichage menu et fréquence actuelle
lcd.setCursor(0, 1); lcd << " -- - + ++ ";
lcd.setCursor(0, 0); lcd << modex[mode] << " F=";
Serial << modex[mode] << " F=";
affiche_valeur(freq,'c',5);
// GBF effectif
tone(sortie_gbf, (unsigned int) freq );
// pour scrutation clavier
tempo_a = 100;
grafcet_a++; // et on passe à l'étape suivante
break;
// gestion clavier
case 502:
// retour au menu général
if (touche == '0') {
noTone(sortie_gbf); // stop GBF
touche = ' ';
grafcet_a=9999; // pour raz grafcet
}
// valeurs calibrées
if (touche == '1') freq = 440.;
if (touche == '2') freq = 880.;
// descente d'une demi-gamme
if (touche == '3') freq /= racine2;
// descente d'un demi-ton
if (touche_repeat == '4') { freq /= demiton; touche_repeat = ' '; }
// montée d'un demi-ton
if (touche_repeat == '5') { freq *= demiton; touche_repeat = ' '; }
// montée d'une demi-gamme
if (touche == '6') freq *= racine2;
// valeurs calibrées
if (touche == '7') freq = 1760.;
if (touche == '8') freq = 3520.;
if (touche == '9') freq = 7040.;
if (touche != ' ') { grafcet_a--; touche = ' '; } // raz touche appuyée
if (tempo_a == 0) grafcet_a--;
break;
//--------------------------------
// Café (en fait, bidouille)
case 1200:
i=0;
grafcet_b=1;
grafcet_a++;
break;
case 1201:
// chenillard
lcd.setCursor(i, 0); lcd << " ";
i++; if (iᡇ) i=0;
lcd.setCursor(i, 0); lcd << "*";
// 2 grafcets
lcd.setCursor(0, 1); lcd << grafcet_a << "ab" << grafcet_b << " ";
lcd.setCursor(11, 1); lcd << tours_ps << " ";
tempo_a = 500; // on arme la tempo
grafcet_a++;
break;
case 1202:
if (touche == '0') {
touche = ' ';
grafcet_b=0;
grafcet_a=9999; // pour raz grafcet
}
if (tempo_a == 0) grafcet_a=1201;
break;
//--------------------------------
// Morse
case 1300:
i=0;
grafcet_a++;
break;
case 1301:
tempo_a = 100;
break;
case 1302:
if (tempo_a == 0) grafcet_a=1301;
break;
//--------------------------------
// si grafcet_a n'a pas une valeur correcte, on passe ici
default:
// arret du grafcet
case 9999:
lcd.clear();
grafcet_a = 10; // on retourne au menu général
break;
}
//--------------------------------
//--------------------------------
//--------------------------------
//--------------------------------
// GRAFCET B
switch (grafcet_b) {
case 1:
if ( tempo_b == 0 ) { // si la tempo est terminée,
horodatage_serial(); Serial << " grafcet_b=" << grafcet_b << " grafcet_a=" << grafcet_a <<endl;
tempo_b = tempo_b_reset; // on arme la tempo
grafcet_b++; // et on passe à l'étape suivante
}
break; // cette instruction vous fait sauter à la fin du "switch"
case 2:
if ( tempo_b == 0 ) {
horodatage_serial(); Serial << " grafcet_b=" << grafcet_b << " grafcet_a=" << grafcet_a << endl;
tempo_b = tempo_b_reset; // on arme la tempo
grafcet_b=1; // on reboucle
}
break;
// si grafcet_a n'a pas une valeur correcte, on passe ici
default:
grafcet_b = 0; // on arrête
break;
} // fin du "switch"
// FIN GRAFCET B
//--------------------------------
}
// ************************************************************************************************
// ************************************************************************************************
// SOUS-PROGRAMMES
// ************************************************************************************************
/* scrutation et filtrage de clavier analogique
utilisation "monocoup" :
if (touche == '1') { ...; touche=' ';}
utilisation avec "répétition" :
if (touche_repeat == '1') { ...; touche_repeat=' ';}
*/
void ger_scrute_clavier(){
// clavier - filtrage
itouche2 = itouche1;
itouche1 = itouche;
itouche = analogRead(clavier);
// pour calibrage
// if (itouche < 1020 ) Serial.println(analogRead(clavier));
// si la touche est stable (3 tours)
if ((itouche)==itouche2) { // && itouche1==itouche2) {
// recherche quelle touche
ntouche=-1;
do {
ntouche++;
} while (itouche > ((xtouche[ntouche]+xtouche[ntouche+1])/2) && ntouche < nbtouche);
// debug lcd.setCursor(0, 1); lcd << "t=" << ltouche[i] << "," << itouche << " "; // 2eme ligne lcd
// si la touche a varié
if (ltouche[ntouche] != vtouche ) {
vtouche = ltouche[ntouche];
// touche valide
if (ntouche < nbtouche) {
touche = vtouche;
touche_repeat = vtouche;
tempo_repeat=800; // duree avant repetition
// arret répétition
} else {
touche_repeat = ' ';
}
// si la touche est la même : repeat ?
} else {
if (ntouche < nbtouche && tempo_repeat == 0 ) {
touche_repeat = vtouche;
tempo_repeat=400; // vitesse repetition
}
}
}
return;
}
// ************************************************************************************************
// Programme au -ieme de seconde
// gestion des temporisations
// NB : le débordement du compteur en (unsigned long) a lieu tous les 50 jours environ ...
void ger_top_centieme (){
unsigned long delta;
unsigned long currentMillis = millis();
// Centième de secondes
delta = currentMillis - previousMillis;
if (delta >= 10) {
// save the last time you come here
previousMillis = currentMillis;
// scrutation du clavier toutes les 10ms
ger_scrute_clavier();
// allumage temporisé led clavier
// if (lamp_tempo >= delta) { lamp_tempo -= delta; digitalWrite(lamp, HIGH); } else { lamp_tempo = 0; digitalWrite(lamp, LOW); }
// gestion des TEMPORISATIONS (en ms mais précise à 10ms près)
if (tempo_a >= delta ) { tempo_a -= delta; } else { tempo_a = 0; }
if (tempo_b >= delta ) { tempo_b -= delta; } else { tempo_b = 0; }
if (tempo_repeat >= delta ) { tempo_repeat -= delta; } else { tempo_repeat = 0; }
// if (fonction_tempo >= delta) { fonction_tempo -= delta; } else { fonction_tempo = 0; }
}
// Dixième de seconde
delta = currentMillis - previousDecis;
if (delta >= 100) {
previousDecis = currentMillis;
top_dixieme = true;
// tops seconde et minute pour traitements dans le main
if (second() != previousSecond) {
previousSecond = second();
top_seconde = true;
if (previousSecond == 0) top_minute=true;
}
}
return;
}
// ************************************************************************************************
// affichage horloge complete sur la sortie serie, sans fin de ligne
void horodatage_serial() {
// digital clock display of the time
Serial << ((day())?"0":"") << day() << "/" << ((month())?"0":"") << month() << "/" << year() << " " << ((hour())?"0":"") << hour() << ":" << ((minute())?"0":"") << minute() << ":" << ((second())?"0":"") << second();
}
// ************************************************************************************************
// ************************************************************************************************
/*
Sur le LCD et la voie SERIE
Affiche la valeur "v" avec "nbchiffres" digits significatifs suivi de l'"unite"
Donc "nbchiffres" digits + point + multiplicateur + unite = "nbchiffres+3" caractères
OK
*/
void affiche_valeur(float v,char unite,int nbchiffres) //,char* sortie)
{
float vloc;
int mult=5,nbdec;
// mult = 0 1 2 3 4 5 6 7 8 9
// multiplicateur = Peta Tera Giga Mega Kilo * milli micro nano pico
char multiple[10] = {'P', 'T', 'G', 'M', 'k', ' ','m', 'u', 'n', 'p'};
vloc=v;
// si valeur inférieure à 1, on multiplie
while (vloc < 1. && mult < 10) {
vloc = vloc*1000;
mult++;
}
// si valeur grande, on divise
while (vloc >= 1000. && mult > 0) {
vloc = vloc/1000;
mult--;
}
// nombre de décimales selon valeur // ex nbchiifres=4 7
nbdec = nbchiffres-3; // 999.9 999.9999
if (vloc < 100 ) nbdec++; // 99.99 99.99999
if (vloc < 10 ) nbdec++; // 9.999 9.999999
// sortie[i]=multiple[mult];
Serial << _FLOAT(vloc, nbdec) << multiple[mult] << unite ;
lcd << _FLOAT(vloc, nbdec) << multiple[mult] << unite ;
return;
}
// ************************************************************************************************
// ************************************************************************************************
Photos de la page :
Dernière mise à jour : 11:40:00 18/09/2020