J'essaie depuis quelque temps de savoir pendant combien de temps un bouton poussoir a était actionné. De ce fait je cherche a calculé la différence de temps entre l'appui et le relâchement a l'aide du Timer 1 de l'arduino. Je me suis aidé de ce cours pour réaliser cette fonction:
J'ai un problème au niveau de comment faire comprendre au programme que je veux faire une aquisition sur front descendant puis sur front montant. Pour l'instant c'est assez aléatoire. Le programme ce bloque généralement en détection de front montant, je n'arrive pas a le faire revenir sur front descendant par la suite
Voilà ce que j'obtient sur le moniteur série, les 2 premières acquisitions fonctionnent, mais les suivantes correspondent plus que a des front montants. Merci de votre aide je sèche pas mal sur ce coup là
Salut lorrio, merci pour ta réponse rapide. Je veux bien essayer ta solution. J'ai juste besoin d'une petite précision, j'utilise quelle fonction pour détecter l'appui puis le relâchement ? J'ai tenté avec deux conditions if mais cela n'a rien donné.
Donc après quelque tests, les solutions proposées ne conviennent pas a mon besoin
Je souhaite pouvoir faire l’acquisition de mon temps d'appuie a n'importe quel moment du programme d'ou mon idée d’utiliser une Interruption via le Timer1.
Je n'ai pas beaucoup progresser depuis hier. Je n'arrive pas a faire "comprendre" au programme que je souhaite qu'il détecte un front descendant puis un front montant. Jusqu’à là, je n'arrive que a avoir l'un ou l'autre. Cela vient probablement du fait que je place mal la demande de changement de détection de front. Si vous pouvez m'orientez comment écrite ce bazar cela serait super. Mon code actuellement :
#define poussoirPin 8
unsigned long duree = 0;
float event = 0;
int nombre = 0;
void setup() {
pinMode (poussoirPin, INPUT_PULLUP);
Serial.begin(115200);
noInterrupts();
TCCR1A = 0;
TCCR1B = 0b00000010; // prediviseur 8 table 16-5 doc atmegaICES1 front descendant =06emebit 7eme bit noise cancel
TIMSK1 = 0b00100001; // autorisation interruption TOV et Input Capture
TCNT1 = 0;
ICR1 = 0;
interrupts();
}
ISR(TIMER1_CAPT_vect) {
TCCR1B = 0b00000010; //front descendant
Serial.println("Appuye");
/*duree = millis();
event = nombre * 32.7675 + ICR1 * 0.0000005;
Serial.println(nombre);
Serial.println(duree);
Serial.println(event);*/
TIFR1 = 0b00100000; //reset du flag C'est cette partie la qui me pose problème, je ne sais pas comment
TCCR1B = 0b01000010; //front montant gérer correctement le changement de détection avec le Timer
Serial.println("Relache");
}
void loop() {
}
Alors déjà, mettre un appel à Serial.println dans une interruption, c'est une très mauvaise idée.
Une interruption doit s'exécuter le plus rapidement possible donc mieux vaut éviter de faire des Serial.print qui prennent énormément de temps.
De plus, sur les dernières versions, il me semble que le driver du Serial est sous interruption donc interdiction de l'utiliser dans une interruption.
Mais sinon, comme je te le disais : pourquoi ne pas utiliser millis et INT0 ???
Exemple de code :
const byte btnPin = 2; // Bouton sur pin 2...
const byte btnIrq = 0; // Bouton sur pin 2, soit INT0 sur arduino UNO.
unsigned long tFall = 0; // Valeur de millis() lors du front descendant
unsigned long tRise = 0; // Valeur de millis() lors du front montant
void onFall(void);
void onRise(void);
void setup(void);
void loop(void);
void onFall() { // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void onRise() { // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void setup(void) { // Setup:
attachInterrupt(btnIrq, onFall, FALLING); // Détection d'interruption sur front descendant au départ
Serial.begin(115200); // Serial à 11500 bauds
}
void loop(void) { // Loop:
if ( ( tRise != 0 ) && ( tFall != 0 ) ) { // Si les 2 fronts ont été détectés, alors on affiche tout
Serial.print("tRise=");
Serial.println(tRise);
Serial.print("tFall=");
Serial.println(tFall);
Serial.print("tDiff=");
Serial.println(tFall-tRise);
}
}
Merci Lorrio ton aide m'a bien débloqué. Par contre il y a un truc que je comprends pas, cela marche a l'envers. Le timer compte le temps ou le Bp n'est pas appuyé au lieu du temps ou il est appuyé . Je me suis dis que cela venait peut etre du fait que j'avais une front montant lors de l'appui sur le Bp mais non cela ne change rien. Une idée de là où ça coince ? Je continue de mon côté .
Mon bp est effectivement câblé dans l'autre sens, j'ai bien un font montant quand j'appuie. Dans le coup j'ai modifié le code
const byte btnPin = 2; // Bouton sur pin 2...
const byte btnIrq = 0; // Bouton sur pin 2, soit INT0 sur arduino UNO.
unsigned long tFall = 0; // Valeur de millis() lors du front descendant
unsigned long tRise = 0; // Valeur de millis() lors du front montant
void onRise(void);
void onFall(void);
void setup(void);
void loop(void);
void onRise() { // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void onFall() { // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void setup(void) { // Setup:
attachInterrupt(btnIrq, onRise, RISING); // Détection d'interruption sur front montant au départ
Serial.begin(115200); // Serial à 11500 bauds
}
void loop(void) {
if ( ( tFall != 0 ) && ( tRise != 0 ) ) {
Serial.print("tRise=");
Serial.println(tRise);
Serial.print("tFall=");
Serial.println(tFall); // Si les 2 fronts ont été détectés, alors on affiche tout
Serial.print("tDiff=");
Serial.println(tFall - tRise);
tRise = 0;
tFall = 0;
}
}
Mais j'ai toujours le même problème. Je compte le temps de relâchement du BP. Vraiment étrange. Je vais tester en détectant seulement un changement d'état sur la broche 2, sans me préoccuper de son niveau précédent. On verra bien ce que cela donne
Les entrées de l'arduino intègrent un pullup, suffit de le demander pinMode(pin, INPUT_PULLUP);
rebonds : ça doit pouvoir aussi se traiter par logiciel / timer : considérer que le bouton est à 1 si il n'est pas passé à l'état 0 pendant n millisecondes, et inversement. (c'est quoi une valeur raisonnable pour un rebond ?)
l'état "1?" représente la situation "ah, ça fait un moment que je ne suis pas revenu à 0, serai-je en train de passer à l'état 1 ?"
Quand le moment commence à être long, timeout, on dit que oui, et on considère qu'on est passé à 1.
Si on a conservé le temps (millis())auquel on est rentré dans (0), et celui où on est rentré dans (1?), ça donne la durée pendant laquelle on considère que le bouton était relâché.
J'ai réussi a faire en sorte que cela fonctionne mais ( bah oui forcement ), j'ai remarqué que lors d'appui trop rapides le programme "ce perd". En effet tFall deviens plus petit que tRise, et donc j'obtiens une valeur qui ne me conviens pas.
Le programme dans sa version qui fonctionne mais il ne faut pas appuyer trop vite ( Merci lorrio ! ).
const byte btnPin = 2; // Bouton sur pin 2...
const byte btnIrq = 0; // Bouton sur pin 2, soit INT0 sur arduino UNO.
unsigned long tFall = 0; // Valeur de millis() lors du front descendant
unsigned long tRise = 0; // Valeur de millis() lors du front montant
unsigned long tDiff =0; //Valeur appuie Bp
void onRise(void);
void onFall(void);
void setup(void);
void loop(void);
void onFall() { // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void onRise() { // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void setup(void) { // Setup:
attachInterrupt(btnIrq, onFall, FALLING); // Détection d'interruption sur front descendant au départ
Serial.begin(115200); // Serial à 11500 bauds
}
void loop(void) {
if ( ( tRise != 0 ) && ( tFall != 0 ) ) {
tDiff= tRise - tFall;
Serial.println(tDiff);
tFall=0;tRise=0;tDiff=0;
/*Serial.print("tRise=");
Serial.println(tRise);
Serial.print("tFall=");
Serial.println(tFall); // Si les 2 fronts ont été détectés, alors on affiche tout
Serial.print("tDiff=");*/
}
}
J'ai enlevé quelques affichages sur le moniteur série, cela a rendu l'acquisition beaucoup plus fluide.
Et ce que cela donne sur le moniteur série. On voit bien ce qui arrive lors d'appui trop frénétique.
Les trois dernières lignes correspondent a des appuis trop rapprochés.
Voilà pour l'instant, je posterai mon avancement dans le développement du programme au fur et à mesure.
L'arduino est un processeur 8bits donc il fait tous les calculs en 8bits.
Si on lui demande de faire des calculs sur des 32bits (unsigned long), il est obligé de le faire en plusieurs fois.
Mais si une interruption se déclenche en pleins milieux, cela peut poser des problèmes.
Par exemple, imaginons que ton programme fasse la soustraction de tDiff et qu'une interruption arrive à ce moment là, alors celle-ci va changer la valeur de tRise ou tFall alors que le processeur était en plein milieu de son opération de soustraction, ce qui donne n'importe quoi comme résultat.
Pour éviter ce problème, il est conseillé de désactiver temporairement les interruptions.
A noter qu'il faut désactiver les interruptions le moins longtemps possible, donc pas de print pendant une désactivation.
Problème presque résolue ( des fois une valeur incorrecte arrive a passer mais cela est assez rare, et il faut vraiment faire des appuis très rapides ).
Le code
const byte btnPin = 2; // Bouton sur pin 2...
const byte btnIrq = 0; // Bouton sur pin 2, soit INT0 sur arduino UNO.
unsigned long tFall = 0; // Valeur de millis() lors du front descendant
unsigned long tRise = 0; // Valeur de millis() lors du front montant
unsigned long tDiff = 0; //Valeur appuie Bp
void onRise(void);
void onFall(void);
void setup(void);
void loop(void);
void onFall() { // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void onRise() { // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void setup(void) { // Setup:
attachInterrupt(btnIrq, onFall, FALLING); // Détection d'interruption sur front descendant au départ
Serial.begin(9600); // Serial à 11500 bauds
}
void loop(void) {
if ( ( tRise != 0 ) && ( tFall != 0 ) ) {
tDiff = tRise - tFall;
Serial.println(tDiff);
tFall = 0; tRise = 0; tDiff = 0;
}
}
Je continue dans la progression de mon travail !
Edit, d'accord lorrio, je verrai l'impact de ce fonctionnement sur le reste du programme. Je garde ça au chaud
Salut a tous Donc c'est bon grâce a vous mon programme fonctionne. Je mémorise correctement le temps d'appuie du BP, et ensuite je peux demander a la Led de s'allumer sur la même durée. La finalité sera de réaliser cela avec un moteur et de commander tout cela via Ethernet normalement.
Le code ci cela intéresses quelqu'un
const byte led = 8; //Led sur pin 8
const byte btnPin = 2; // Bouton sur pin 2...
const byte btnIrq = 0; // Bouton sur pin 2, soit INT0 sur arduino UNO.
unsigned long tFall = 0; // Valeur de millis() lors du front descendant
unsigned long tRise = 0; // Valeur de millis() lors du front montant
unsigned long tDiff = 0; //Valeur appuie Bp
unsigned long mem; //Variable mémoire
byte varCompteur = 0; // La variable compteur
char c;
void onRise(void);
void onFall(void);
void setup(void);
void loop(void);
void onFall() { // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void onRise() { // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void setup(void) {
pinMode(led, OUTPUT);
attachInterrupt(btnIrq, onFall, FALLING); // Détection d'interruption sur front descendant au départ
Serial.begin(9600); // Serial à 9600 bauds
}
void loop(void) {
digitalWrite(led, LOW);
while (Serial.available()) {
c = Serial.read();
if ( c == 'a') { //Mode "apprentissage"
if ( ( tRise != 0 ) && ( tFall != 0 ) ) {
tDiff = tRise - tFall; //On fait la diffèrence entre l'appui et le relachement
Serial.println(tDiff); //On affiche le temps d'appui
mem = tDiff; // On sauvegarde la valeur de tDiff dans mem
tFall = 0; tRise = 0; tDiff = 0; //On remets les variables a zéro
}
}
if ( c == 'b') { //Mode "automatique" la led reste allumée pendant le meme temps que tDiff
digitalWrite(led, HIGH);
delay(mem);
}
}
}
<code >
const byte btnPin = 2; // Bouton sur pin 2...
const byte btnIrq = 0; // Bouton sur pin 2, soit INT0 sur arduino UNO.
unsigned long tFall = 0; // Valeur de millis() lors du front descendant
unsigned long tRise = 0; // Valeur de millis() lors du front montant
unsigned long tDiff =0; //Valeur appuie Bp
void onRise(void);
void onFall(void);
void setup(void);
void loop(void);
void onFall() { // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void onRise() { // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void setup(void) { // Setup:
attachInterrupt(btnIrq, onFall, FALLING); // Détection d'interruption sur front descendant au départ
Serial.begin(115200); // Serial à 11500 bauds
}
void loop(void) {
if ( ( tRise != 0 ) && ( tFall != 0 ) ) {
tDiff= tRise - tFall;
Serial.println(tDiff);
tFall=0;tRise=0;tDiff=0;
/*Serial.print("tRise=");
Serial.println(tRise);
Serial.print("tFall=");
Serial.println(tFall); // Si les 2 fronts ont été détectés, alors on affiche tout
Serial.print("tDiff=");*/
}
}
< /code>
Cependant je n'arrive pas à donner un déclenchement sur le Pin 8 en fonction de la valeur de tDiff ( compris entre deux valeurs )
Le pin 8 Active un relais.
Je n'arrive pas à saisir un code correct.
Pouvez vous m'aider ?
Merci d'avance
Voici mon script, il fonctionne une pièce sur deux ( quelque soit l'intervalle de temps de passage )
<code >
// DECLARATION DES CAPTEURS
int air = 8; // vers relais AIR
const byte cap = 2; // vers CAPTEUR LASER
const byte btnIrq = 0;
// DETECTION DES FRONTS
static unsigned long tFall = 0; // Valeur de millis() lors du front descendant
static unsigned long tRise = 0; // Valeur de millis() lors du front montant
unsigned long tDiff = 0; //Valeur appuie Bp
unsigned long mem; //Variable mémoire
//SETUP
void onRise(void);
void onFall(void);
void setup(void);
void loop(void);
void onFall()
{ // Interruption lors d'un front descendant
tFall = millis(); // On sauvegarde la valeur de millis dans tFall
attachInterrupt(btnIrq, onRise, RISING); // Puis on passe la détection d'interruption sur front montant
}
void onRise()
{ // Interruption lors d'un front montant
tRise = millis(); // On sauvegarde la valeur de millis dans tRise
attachInterrupt(btnIrq, onFall, FALLING); // Puis on passe la détection d'interruption sur front descendant
}
void setup(void)
{
// PULLUP
pinMode(cap, INPUT_PULLUP);
//
pinMode(air, OUTPUT);
attachInterrupt(btnIrq, onFall, FALLING); // Détection d'interruption sur front descendant au départ
///////////////////
Serial.begin(115200); // Serial à 9600 bauds
}
void loop(void) {
digitalWrite(air, LOW);
noInterrupts();
///////////////0
if ( ( tRise != 0 ) && ( tFall != 0 ) )
{
tDiff = ( tRise - tFall );
mem = tDiff;
}
interrupts();
if ( mem > 150 && mem < 300 )
{
Serial.println(tDiff);
// Serial.println(tDiff);
//Serial.println(tFall);
//Serial.println(tRise);
digitalWrite(air, HIGH);
delay(300); // EXPULSION DE LA PIECE
// digitalWrite(air, LOW);
mem = 0; tFall = 0; tRise = 0; tDiff = 0; // REMISE A ZERO
}}
< /code>
- Edité par FrankLessard 23 août 2019 à 21:16:21
[Arduino] Calcul du temps qu'un Bp est appuyé
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Bonhomme !! | Jeu de plateforme : Prototype.