Pages: [1]   Go Down
Author Topic: Boucle interrompue par une commande  (Read 751 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Je viens juste de recevoir mon Arduino Uno nue je ne peux donc que "jouer" avec une LED. En partant du programme de base j'ai commencé à envoyer des commandes pour allumer et éteindre la LED via Serial. Le problème c'est que je n'arrive pas a interrompre une 3° fonction qui est le clignotement de ma diode par une autre commande. Je m'explique:

Si j'envoie "+" via le terminal de commandes j'allume ma diode.
Si j'envoie "-" via le terminal de commandes j'éteins ma diode.
Si j'envoie "=" je la fais clignoter.
Cependant si je renvoie "+" la diode continue a clignoter car la carte est restée dans la boucle de clignotement de la diode (j'allume et j'éteins avec un delay de 1000).

HELP!

J'ai vu qu'il existait une procédure "interrupt" mais j'ai l'impression que cela ne sert qu'aux interrupteur matériels et pas à faire des "fork"/"threads".

Voici mon code :
Code:
const int ledPin = 13;  
int ledState = LOW;
boolean interrupt = true;

void setup()  
{  
  Serial.begin(9600);  
  pinMode(ledPin, OUTPUT);  
}  
  
void loop()  
{  
  while (Serial.available())  
  {  
    char key = Serial.read();  
    switch (key)  
    {  
    case '+':  
      interrupt = true;
      ledState = HIGH;
      break;  
    case '-':
      interrupt = true;
      ledState = LOW;
      break;
    case '=':
      interrupt = false;
      loopLed();
      break;
    default:  
      Serial.print("commande ");  
      Serial.print(key);  
      Serial.println(" non reconnue.");  
      break;  
    }  
    digitalWrite(ledPin, ledState);
  }  
}  

void loopLed()
{
  if (ledState == LOW)
    ledState = HIGH;
  else
    ledState = LOW;
  digitalWrite(ledPin, ledState);
  delay(1000);
  if(!interrupt)
    loopLed();
}
Logged

Central Europe
Offline Offline
Edison Member
*
Karma: 7
Posts: 1220
Use the Source, Luke.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai vraiment besoin d'un touche qui me rajoute le liens vers l'exemple BlinkWithoutDelay.

Ton problème vient du fait que dés que ton programme commence à clignoter, il ne fait rien d'autre, ce qui inclus lire des commandes. De plus, ta fonction loopLed() fait une récursion à la fin, ce qui n'est pas forcement faux, mais te bouffe les 2 kB de mémoire dans l'ATmega328 rapidement.

Donc vire la fonction loopLed, delay() et toutes les boucles de ls fonction loop() et travaille avec millis(). Pour ce que tu veux faire, la boucle externe qui démarre loop() en perpétuité suffit, tu n'as pas besoin d'autres boucles.

Korman
« Last Edit: December 02, 2010, 07:16:24 pm by Korman » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Merciiiiiiiiiiii ^^

Voici mon code final si ça intéresse un autre Noob comme moi :
Code:
const int ledPin = 13;  
int ledState = LOW;
boolean interrupt = true;
long interval = 1000;
long previousMillis = 0;

void setup()  
{  
  Serial.begin(9600);  
  pinMode(ledPin, OUTPUT);  
}  
  
void loop()  
{  
  
  if(!interrupt)
  {
    unsigned long currentMillis = millis();
 
    if(currentMillis - previousMillis > interval) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;  
  
      // if the LED is off turn it on and vice-versa:
      if (ledState == LOW)
        ledState = HIGH;
      else
        ledState = LOW;
  
      // set the LED with the ledState of the variable:
      digitalWrite(ledPin, ledState);
      Serial.print("(=) ");
      Serial.print("Etat Diode :");
      Serial.println(ledState);
    }
  }
  
  while (Serial.available())  
  {  
    char key = Serial.read();  
    switch (key)  
    {  
    case '+':  
      interrupt = true;
      ledState = HIGH;
      break;  
    case '-':
      interrupt = true;
      ledState = LOW;
      break;
    case '=':
      interrupt = false;
      break;
    default:  
      Serial.print("commande ");  
      Serial.print(key);  
      Serial.println(" non reconnue.");  
      break;  
    }  
    digitalWrite(ledPin, ledState);
    Serial.print("(");
    Serial.print(key);
    Serial.print(") ");
    Serial.print("Etat Diode :");
    Serial.println(ledState);
  }  
}  
Logged

Montréal
Offline Offline
Newbie
*
Karma: 0
Posts: 48
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Et si tu veux une solution compliqué, utilise le "TaskManager" de ma librairie (ok, c'est pas encore disponible, mais ça s'en vient  smiley-wink )

ça ressemblerais à ça:

Code:

#include <TaskManager.h>

boolean ledState ;

void SetLedState(boolean val)
{
    ledState = val ;
    digitalWrite(13,val) ;
}

void ToggleLed(void)
// va être appelé au 250 millisec
{
    SetState(!ledState) ;
}

void setup()
{
  Serial.begin(9600) ;
  pinMode(13,OUTPUT) ;
  SetLedState(false) ;
  TaskManager.Setup(TM_50MS) ; // base de temps 50 milli
  TaskManager.Add(ToggleLed,5)  ; // appel de ToggleLed au 250 ms (50 ms* 5)
}

void loop()
{
  char car ;
  bool led,cligne ;

  if (Serial.available())
     {
        switch  (Serial.Read())  // scuzez l'indentation approximative
           {
              case '+' : SetLedState(true) ;
                            TaskManager.Enable(ToogleLed,false) ;
                            break ;
              case '-' : SetLedState(false) ;
                           TaskManager.Enable(ToogleLed,false) ;
                           break ;
              case '=' : TaskManager.Enable(ToogleLed,true) ;
                            break ;
              default :  Serial.Print("erreur") ;
      }
    }

         

Au Québec, on appelle ça une plogue publicitaire.  smiley-wink smiley-wink  
« Last Edit: December 02, 2010, 01:39:53 pm by Guyt54 » Logged

Pages: [1]   Go Up
Jump to: