Alternatives d’interruption Arduino

D’après ce que j’ai lu, la solution à mon problème consiste à utiliser une interruption, mais si je les comprends bien, je ne peux pas utiliser de délai dans la routine appelée par cette interruption. J’ai un gros bouton-poussoir LED . Je veux que le cœur batte au ralenti, mais une fois que vous avez appuyé dessus, restz vert et exécutez le code.

Je peux interrompre le heartbeat() si j’appuie suffisamment sur le bouton (je suppose que le changement d’état se produit au bon moment lorsqu’il termine une boucle du heartbeat ), mais je suis bloqué sur la façon de le faire fonctionner le premier. Cliquez sur. Y at-il une autre façon de faire ce que je tente?

 void loop(){ heartbeat(); //Make LED beat. buttonVal = digitalRead(buttonPin); //Check the button. if (buttonVal != buttonState) { //If the button state changed. if (buttonVal == HIGH){ //Check if the button is pressed. analogWrite(greenPin, 255); //Button stays green once pushed. functionA //Has some delays in it. functionB //Has some other delays. } } } void heartbeat(){ for(i = 0; i  0; i--){ analogWrite(greenPin,i); delay(((60000/rate)*.2)/pmw); } for(i = 0; i  0; i--){ analogWrite(greenPin,i); delay(((60000/rate)*.6)/pmw); } } 

Vous avez raison dans la plupart de vos hypothèses. La bonne façon de gérer cela consiste à utiliser une interruption et ce n’est pas une bonne idée d’attendre des retards dans vos routines de service d’interruption (ISR). Donc, ce que vous voulez faire est de définir un drapeau dans votre ISR et de vérifier ce drapeau dans votre boucle principale.

 // Flag needs to be volatile if used in an ISR volatile int buttonFlag = 0; void loop() { if (buttonFlag == 0) { heartbeat(); //make led beat } else { analogWrite(greenPin, 255); //button stays green once pushed functionA //has some delays in it functionB //has some other delays buttonFlag = 0; //clear flag after executing code } } // Interrupt Service Routine attached to INT0 vector ISR(EXT_INT0_vect) { buttonFlag = digitalRead(buttonPin); //set flag to value of button } 

Comme l’interruption ne se déclenchera que lors d’un changement d’état du bouton, vous n’avez pas besoin de vérifier cela.

Assurez-vous que votre variable de drapeau est globale et est déclarée volatile pour pouvoir être utilisée dans l’ISR. Et assurez-vous que vous utilisez le bon vecteur d’interruption à utiliser avec la broche que vous utilisez.

Voici un bon tutoriel sur les interruptions Arduino. Et voici un autre bon exemple de ce que vous essayez de faire.

Vous voudrez peut-être aussi examiner la possibilité de supprimer le rebond de vos commutateurs en fonction du type de commutateur que vous utilisez. Si au lieu de manquer la première presse, vous obtenez trop de presses, vous devrez implémenter un type de suppression du rebond.

Je suis un programmeur professionnel, mais je suis nouveau dans le monde Arduino. J’ai remarqué que beaucoup de propriétaires d’Arduino ne connaissent pas les bases de la programmation et ne peuvent obtenir de bons résultats en utilisant cette technologie incroyable.

En particulier, je souhaite suggérer de ne pas utiliser les interruptions Arduino si elles ne sont pas nécessaires, car elles ne sont que deux, et même si vous pouvez écrire un “beau” code pour un seul capteur, ou actionneur, lorsque vous devez implémenter une projet plus complexe, vous ne pouvez pas les utiliser. Vous avez sûrement eu raison d’utiliser l’interruption pour gérer un seul bouton, mais que faire si vous avez quatre boutons à gérer?

Pour cette raison, j’ai réécrit l’esquisse “Heartbeat” en utilisant la technique de “tranche temporelle” ou “étape simple”. En utilisant cette technique, chaque fois que la fonction de boucle est exécutée, vous n’exécutez qu’une seule étape de vos fonctions de contrôle. Vous pouvez donc en insérer autant que vous le souhaitez, et être également rapide et réactif vis-à-vis de tous les capteurs que vous utilisez. Pour ce faire, j’utilise des compteurs globaux pour chaque fonction de contrôle que je dois implémenter et, chaque fois que la fonction de boucle est exécutée, j’exécute une étape unique de chaque fonction. Voici le nouveau croquis:

 // Interrupt.ino - this sketch demonstrates how to implement a "virtual" interrupt using // the technique of "single step" to avoid heavy duty cycles within the loop function. int maxPwm = 128; // max pwm amount int myPwm = 0; // current pwm value int phase = 1; // current beat phase int greenPin = 11; // output led pin int buttonPin = 9; // input button pin int buttonFlag = 1; // button flag for debounce int myDir[] = {0,1,-1,1,-1}; // direction of heartbeat loop int myDelay[] = {0,500,1000,500,3000}; // delay in microseconds of a single step void setup() { pinMode(buttonPin, INPUT); // enable button pin for input // it's not necessary to enable the analog output } void loop() { if(phase>0) heartbeat(); // if phase 1 to 4 beat, else steady buttonRead(); // test if button has been pressed } // heartbeat function - each time is executed, it advances only one step // phase 1: the led is given more and more voltage till myPwm equals to maxPwm // phase 2: the led is given less and less voltage till myPwm equals to zero // phase 3: the led is given more and more voltage till myPwm equals to maxPwm // phase 4: the led is given less and less voltage till myPwm equals to zero void heartbeat() { myPwm += myDir[phase]; analogWrite(greenPin, myPwm); delayMicroseconds(myDelay[phase]); if(myPwm==maxPwm||myPwm==0) phase = (phase%4)+1; } // buttonRead function - tests if the button is pressed; // if so, forces phase 0 (no beat) and enlightens the led to the maximum pwm // and remains in "inoperative" state till the button is released void buttonRead() { if(digitalRead(buttonPin)!=buttonFlag) // if button status changes (pressed os released) { buttonFlag = 1 - buttonFlag; // toggle button flag value if(buttonFlag) // if pressed, toggle between "beat" status and "steady" status { if(phase) myPwm = maxPwm; else myPwm = 0; phase = phase==0; analogWrite(greenPin, myPwm); } } } 

Comme vous pouvez le constater, le code est très compact et rapide à exécuter. J’ai divisé la boucle de pulsation en quatre “phases”, régulées par le tableau myDelay, et dont la direction de comptage est régulée par le tableau myDir. Si rien ne se produit, la tension de la broche led pwm est incrémentée à chaque étape jusqu’à atteindre la valeur maxPwm, puis la boucle entre en phase 2, dans laquelle la tension est décrémentée jusqu’à zéro, et ainsi de suite, en implémentant le battement de coeur d’origine.

Si vous appuyez sur le bouton, la boucle entre en phase zéro (pas de pulsation) et la led est alimentée avec la tension maxPwm. A partir de maintenant, la boucle rest allumée jusqu’à ce que le bouton soit relâché (ceci met en œuvre l’algorithme “debounce”). Si vous appuyez de nouveau sur le bouton, la fonction buttonRead relance la fonction de pulsation, la faisant entrer à nouveau dans la phase 1, de sorte que la pulsation est restaurée.

Si vous appuyez à nouveau sur le bouton, le battement de coeur s’arrête, etc. Le tout sans aucune exaltation ni rebondissement.