Bonjour
Voici un programme simple de "filtre numérique" pour le schéma proposé précédemment, le programme est prévu pour une seule zone (mais peut être facilement étendu). L'idée de base est la suivante :
- lors d'une détection d'occupation celle ci est transmise immédiatement à celui qui la traite
- lors d'une détection de libération une temporisation de quelques secondes (1, 2 ou 3 s) est mise en oeuvre avant de la transmettre à celui qui la traite
Quelques complications sont nécessaires pour palier la mauvaise qualité du signal sortant de l'optocoupleur, ainsi que les mauvaises prises de courant des engins moteurs (ou remorqués)
Voici le programme pour un Arduino:
const byte pin=1; // choix de la pin d'entree
const int retard=3000; // retard a la liberation (milis-secondes)
unsigned long temps; // pour la temporisation
void setup() {
pinMode(pin,INPUT); // mise en entree
temps=0; // initialisation
}
void loop() { byte x;
x=digitalRead(pin); // lecture de la pin
if (x==0) { // occupation de la zone ?
if (temps==0) Serial.println("occupation de la zone");
temps=millis(); // re-armement de la temporisation
}
else { // liberation de la zone ?
if (temps!=0 && millis()-temps>retard) { // pas libre et temporisation echue ?
Serial.println("liberation de la zone");
temps=0; // re-initialisation
}
// else rien (la liberation est toujours temporisee)
}
}
On a besoin de deux constantes et d'une variable :
- le numéro de la pin utilisée
- le retard à la libération
- un temps qui sert à mettre en oeuvre le retard à la libération (temporisation)
Le setup() règle la pin en entrée et initialise le temps.
Le loop() teste indéfiniment l'état de la pin :
- on lit la pin, si c'est zéro c'est une occupation (le transistor de l'optocoupleur fait une inversion)
- si le temps est à zéro c'est un début d'occupation, on transmet l'information à celui qui la traite
- dans tous les cas on mémorise dans temps le temps courant (pour la temporisation de libération)
- sinon (pin à un) c'est une libération
- on regarde si on est au bout de la temporisation (pour palier la mauvaise qualité du signal sortant de l'optocoupleur, ou les aléas de prise de courant), si oui la libération est transmise à celui qui la traite et on remet le temps à zéro
Celui qui traite les occupations/libérations de zones ne reçoit une information que lors d'une vraie occupation ou d'une vraie libération de zone, ceci grâce au "filtre numérique" mis en oeuvre.
On peut facilement prendre en compte plusieurs zones (plusieurs dizaines, voire centaines) en adaptant le programme et en utilisant plusieurs pins de l'Arduino, on peut aussi utliliser des mutiplexeurs, des registres à décalage, … pour utiliser moins de pins de l'Arduino. Il faut faire néanmoins attention à l'encombrement mémoire, chaque zone a besoin d'une variable "temps" qui fait quatre octets, par exemple pour 64 zones cela fait 256 octets (1/8 de la RAM d'un Uno !).
Avec plusieurs zones le loop() teste une zone après l'autre indéfiniment, il faut que ce temps de traitement soit suffisamment bref, une prise en compte rapide des occupations est par exemple nécessaire pour une poursuite en canton en analogique (voir l'article
http://www.locoduino.org/spip.php?article184).
L'horloge de l'Arduino, donc le résultat de millis() repasse par zéro tous les 50 jours environ, lors de ce retour à zéro le filtrage numérique peut avoir un comportement erratique (on pourrait améliorer le filtrage pour palier ce problème).
Quand on démarre un Arduino (mise sous tension ou reset) l'horloge repart à zéro, et il faut un délai de 1 ms pour que le filtrage fonctionne bien (la valeur zéro est utilisée comme cas particulier pour économiser la mémoire).
On pourrait mettre en oeuvre un filtrage plus contraignant, par exemple en exigeant un signal d'occupation pour plusieurs passages successifs dans le loop() (avec un compteur) avant de transmettre une vraie occupation.
Pierre