Bonjour,
A toutes fins utiles, je propose ici un système qui permet d'associer une Led et un Bouton, sur la même pin.
J'utilise ce système dans le module de traction de mon projet :
http://forum.locoduino.org/index.php?topic=290.msg3999#msg3999Le schéma est le suivant :

Pour chaque loco, j'ai un potentiomètre pour régler la vitesse, un bouton pour changer de direction (conditionné par la vitesse = 0) et 2 leds une verte pour indiquer la marche avant et une rouge pour indiquer la marche arrière.
De plus, chaque bouton doit être "débouncé" c'est à dire qu'il faut lire son état 2 fois avec un intervalle de quelques millisecondes (25 dans mon cas). Le principe est simple pour gérer le bouton et la led : alternativement la pin est en INPUT et en OUTPUT.
Le code est le suivant :
bool CmdMaj( bool d) {
bool dir = d;
bool change = false;
bool buttonValue;
if (millis()-previousTime >= intervalTime) {
previousTime = millis();
pinMode(pinLedVerte, INPUT);
buttonValue = digitalRead(pinLedVerte);
if (buttonValue != buttonVState) { // changement d'etat de la pin
switch (this->etat) {
case 0:
if (!buttonValue) { // 1er appui
this->etat = 1; // attente confirmation
}
break;
case 1:
if (!buttonValue) { // confirmation d'appui
buttonVState = buttonValue; // nouvel ancien etat de la pin
dir = !dir; // inversion sens de marche
this->etat = 2; // appui en cours, do nothing
change = true; // job done !
}
break;
case 2:
if (buttonValue) { // relaché
this->etat = 3; // attente confirmation
}
break;
case 3:
if (buttonValue) { // relaché
buttonVState = buttonValue; // nouvel etat
this->etat = 0; // fin process
}
}
}
pinMode(pinLedVerte, OUTPUT);
digitalWrite(pinLedRouge, dir);
digitalWrite(pinLedVerte, !dir); // allume si false
}
return (change);
}
Enfin, pour commander une loco avec le potentiomètre, le bouton et les leds, j'ai fait une classe :
class CmdLoco {
private :
int pinLedVerte; // et bouton
int pinLedRouge;
int pinPotar;
unsigned long previousTime ;
unsigned int intervalTime;
int etat; // 0 : attente, 1 : 1er changement, 2 : confirmation
bool buttonVState;
bool marcheAvant;
int potValue;
public :
CmdLoco(int pLV, int pLR, int pPot, int pIt) { // constructeur
pinLedVerte = pLV;
pinLedRouge = pLR;
pinPotar = pPot;
intervalTime = pIt;
}
void CmdInit() {
marcheAvant=true;
pinMode(pinLedVerte, OUTPUT);
pinMode(pinLedRouge, OUTPUT);
digitalWrite(pinLedVerte, !marcheAvant); // allume si false
digitalWrite(pinLedRouge, marcheAvant); // eteinte
previousTime = millis();
this->etat = 0;
buttonVState = true;
}
void MajLed(bool d) {
digitalWrite(pinLedRouge, d);
digitalWrite(pinLedVerte, !d); // allume si false
}
bool CmdMaj( bool d) {
bool dir = d;
bool change = false;
bool buttonValue;
if (millis()-previousTime >= intervalTime) {
previousTime = millis();
pinMode(pinLedVerte, INPUT);
buttonValue = digitalRead(pinLedVerte);
if (buttonValue != buttonVState) { // changement d'etat de la pin
switch (this->etat) {
case 0:
if (!buttonValue) { // 1er appui
this->etat = 1; // attente confirmation
}
break;
case 1:
if (!buttonValue) { // confirmation d'appui
buttonVState = buttonValue; // nouvel ancien etat de la pin
dir = !dir; // inversion sens de marche
this->etat = 2; // appui en cours, do nothing
change = true; // job done !
}
break;
case 2:
if (buttonValue) { // relaché
this->etat = 3; // attente confirmation
}
break;
case 3:
if (buttonValue) { // relaché
buttonVState = buttonValue; // nouvel etat
this->etat = 0; // fin process
}
}
}
pinMode(pinLedVerte, OUTPUT);
digitalWrite(pinLedRouge, dir);
digitalWrite(pinLedVerte, !dir); // allume si false
}
return (change);
}
}; // fin classe CmdLoco
L'utilisation de cette classe est simple :
1) déclarer mes 12 locos dans un table :
//--- TABLE DES LOCOS
CmdLoco * gTableCloco[MaxLocos]; // Table des locos
2) Créer les objets et les initialiser :
//--- creation des objets Cloco et de la table
for (int L=0; L<MaxLocos; L++) {
gTableCloco[L] = new CmdLoco(ledVerte[L],ledRouge[L],gPotPin[L], 25); // ledVerte, ledRouge, pot, intervalTime)
}
//--- initialisation des objets Cloco
for (int L=0;L<MaxLocos;L++) {
gTableCloco[L]->CmdInit();
}
Pour terminer, voici le bout de code qui est dans loop() pour utiliser cette classe :
// potentiometres
for (int i = 0; i < 12; i++) {
gSensorValue = analogRead(gPotPin[i]);
gOutputValue = map(gSensorValue, 0, 1023, 0, 127);
if (gOutputValue != gPot[i]) {
gPot[i] = gOutputValue;
gLocoSpeed[i] = gPot[i];
gPotChange = true;
DccDirection = gLocoDirection[i];
if (gCurrentLoco.inverse) {DccDirection = !DccDirection;}
DCCpp::setSpeedMain(gConfigLocos[i].registre, gConfigLocos[i].dccAddress, gLocoStepsNumber, gLocoSpeed[i], DccDirection);
}
}
// boutons et leds de direction
for (int u=0;u<MaxLocos;u++) {
if (gLocoSpeed[u] == 0) {
if (gTableCloco[u]->CmdMaj(gLocoDirection[u])) {
gLocoDirection[u] = !gLocoDirection[u];
}
}
}
Chacun en déduira quelles sont les variables globales utilisées.
Bon Noël à tous