[HELP] Programmation Arduino Uno

Répondre
Partager Rechercher
Salut les gars,

Je cherche à faire un programme (en C pour Arduino donc) permettant de faire clignoter des LED avec 3 modes différents. Le souci, c'est que chaque mode se trouve dans une boucle while (pour pouvoir continuer indéfiniment si on reste sur le même mode) et que je dois utiliser un interrupteur 3 positions pour le switch. De cet interrupteur, je récupère 3 pattes que j'ai connecté aux entrées digitales de ma carte et suivant l'état de ces 3 pattes (0 ou 5V), je dois donc changer de mode.

J'avais fait une première tentation en simplement réunissant les 3 programmes dans le void loop() en mettant des conditions au niveau de chaque boucle while :
Code:
while(z==HIGH)
{
   //sous programme
}
Je pense qu'il faut que je passe par les interruptions. J'ai essayé de faire quelque chose (ce ne sont pas les vrais sous programme, c'est juste pour tester là), mais ça ne fonctionne pas.

Code:
int rouge = 11;
int vert = 10;
int bleu = 9;
int inter1 = 2;
int inter2 = 3;
int a;
int x;
int y;
int z;
int i;
int p;


// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(rouge, OUTPUT);
  pinMode(vert, OUTPUT);
  pinMode(bleu, OUTPUT);
  attachInterrupt(0, interruption, CHANGE);
  attachInterrupt(1, interruption, CHANGE);  

}

// the loop routine runs over and over again forever:
void loop() 
{

  i=500;
  
  if(p=1)
  {
  while(p=1)
  {
    analogWrite(rouge,255);
    analogWrite(vert,255);
    analogWrite(bleu,255);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }
  }
  
  if(p=2)
  {
  while (p=2)
  {
    analogWrite(rouge,0);
    analogWrite(vert,255);
    analogWrite(bleu,255);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }
}

if(p=3)
{
  while (p=3)
  {
    analogWrite(rouge,255);
    analogWrite(vert,0);
    analogWrite(bleu,255);

  } 
}

}



void interruption ()
{
  x = digitalRead(inter1);
  y = digitalRead(inter2); 

  if(x==LOW && y==HIGH)
  {
    p=1;
  }

  if(x==HIGH && y==HIGH)
  {
    p=2;
  }

  else
  {
    p=3;
  }
}

Est ce qu'il y en a qui s'y connaissent un peu et qui peuvent m'aider ?

Merci d'avance.
Salut,

Je connais rien à l'Arduino et j'ai pas fait de C depuis un moment.

Premièrement, quelle est l'erreur que tu obtiens ? A la compilation ou à l'exécution ?
Ensuite, si je comprends bien l'appel à attachInterrupt va modifier la valeur de p ; il faut donc qu'à chaque "pas" tu appelles cette routine pour que p soit updaté et que le cas échéant tu passes à une autre LED. Dans ta routine loop tu n'appelles jamais de routine mettant à jour p donc j'imagine que tu restes bloqué à ton état initial.
Quel est l'intérêt de faire trois while sachant que de toute manière tu as la boucle (loop) principale du programme ?

Déjà fais une variable de genre booléenne qui switch à chaque passage de la loop, je sais pas si ça existe sur Arduino mais le principe c'est :

Code:
if(varBool == true)
{
varBool = false;
}
else
{
varBool = true;
}
Et cette variable définira si tu as de la tension ou pas dans tes leds. Si y'a pas de type booléen tu fais ça avec 0 et 1. Si le type bool existe, alors tu peux faire ça beaucoup plus simplement ainsi :

Code:
varBool = !varBool;
Ensuite, inutile de faire trois while ! Essaie ce type de structure (j'écris à l'arrache mais tu verras un peu le principe) :

Code:
void loop()
{
     varBool != varBool;
    //Ou l'autre solution plus longue si pas de type bool
     if(varBool == false)
     {
        analogWrite(rouge,0);
        analogWrite(vert,0);
        analogWrite(bleu,0);
     }
     else
     {
        if(couleur==bleu)
       {
           //afficher bleu
        }
        elsif(couleur==rouge)
        {
            //afficher rouge
         }
        elsif(couleur==vert)
        {
            //afficher vert
         }
     }
}
Pour ton histoire d'interruption et tout, j'ai jamais fait ça sur Arduino donc je peux pas trop t'aider. Mais teste ton programme partie par partie. Essaie déjà de faire un programme qui clignote en une couleur, puis en 3 (qui change par exemple quand il a clignoté 100x d'une couleur), puis finalement tente avec tes interrupts.

Dernière modification par Sergul ; 18/03/2014 à 15h14.
J'ai pas trop compris le pb de l'OP, mais:

Code:
if (p==1)
   while (p==1)
   {
   //stuff
    }
Le if ne sert à rien

Sinon il y a une typo Sergul
Code:
varBool = !varBool;
Et pour l'OP, si tu as copié-collé tu fais des assignations dans ta boucle principale au lieu de faire des tests (= au lieu de ==), en général ça pose problème .
Alors merci pour vos réponses. Effectivement, le coup du if... while, ça sert à rien (c'était juste pour test).

J'ai pas trop compris où vous vouliez en venir avec les booléens et à vrai dire, je suis pas sûr que ça fonctionne. Parce qu'en fait, j'ai jamais 0V sur mes pins, j'ai toujours quelques µV voire mV du coup, du coup ça merde avec la condition "LOW" (qui correspond à un état bas (0V) sur la pin). Je suis donc passé par des AnalogRead au lieu des digitalRead afin de récupérer une valeur entre 0 et 1023 en fonction de la tension et j'ai créé une question sur cette valeur.
Plus besoin des interruptions qui foutait la merde dans le programme (je les utilisais ailleurs).

Voilà le programme complet pour les curieux.
Code:
//Déclare les pins
int rouge = 11;
int vert = 10;
int bleu = 9;
int uv = 6;
int potar = A0;
int analogPin = A1;
int i;
int potarValeur;
int inter1 = A2;
int inter2 = A3;
int inter3 = A4;
int x;
int y;
int z;
void allumageLED(int , int);
void couleuraleatoire(void);
void couleurfixe(void);
void leduv (void);
int n=0;


void setup() {
  //Déclare l'état des pins
  pinMode(rouge, OUTPUT);
  pinMode(vert, OUTPUT);
  pinMode(bleu, OUTPUT);
  pinMode(uv, OUTPUT); 

}

void loop()
{
  
  //LECTURE DES VALEURS DES POTAR
  i = analogRead(analogPin);
  
  z = analogRead(inter1);
  y = analogRead(inter2);
  x = analogRead(inter3);

  
  if(z>=1000 && x >= 1000 && y <= 1000)
  {
    leduv();
  }
  if(x>=1000 && y<=1000 && z <= 1000)
  {  
  couleuraleatoire();
  }      
  if(y>= 1000 && x <= 1000 && z <= 1000)
  {
  couleurfixe();
  }
             
}


void couleuraleatoire()
{
  if(n == 5){
  potarValeur = random(129,1023);
  n = 0;
  }
  n =n + 1;
  allumageLED(potarValeur,i);
}

void leduv()
{
  analogWrite(uv,255);
  delay(i);
  analogWrite(uv,0);
  delay(i);
}

void couleurfixe()
{
  potarValeur = analogRead(potar);
  allumageLED(potarValeur, i);
}


void allumageLED(int potarValeur, int i)
{
  if (potarValeur >= 0 && potarValeur <= 128) {
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
    
  }
  //ROUGE
  if (potarValeur >= 129 && potarValeur <= 256) {
 
    {
      analogWrite(rouge,255);
      analogWrite(vert,0);
      analogWrite(bleu,0);
      delay(i);
      analogWrite(rouge,0);
      analogWrite(vert,0);
      analogWrite(bleu,0);
      delay(i);
    }
  }

  //VERT
  if (potarValeur >= 257 && potarValeur <= 384) {
    analogWrite(rouge,0);
    analogWrite(vert,255);
    analogWrite(bleu,0);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }

  //BLEU
  if (potarValeur >= 385 && potarValeur <= 512) {
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,255);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }

  //JAUNE
  if (potarValeur >= 513 && potarValeur <= 640) {
    analogWrite(rouge,255);
    analogWrite(vert,255);
    analogWrite(bleu,0);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }
  //VIOLET
  if (potarValeur >= 641 && potarValeur <= 768) {
    analogWrite(rouge,255);
    analogWrite(vert,0);
    analogWrite(bleu,255);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }
  //CYAN
  if (potarValeur >= 769 && potarValeur <= 896) {
    analogWrite(rouge,0);
    analogWrite(vert,255);
    analogWrite(bleu,255);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }
  //BLANC
  if (potarValeur >= 897 && potarValeur <= 1023) {
    analogWrite(rouge,255);
    analogWrite(vert,255);
    analogWrite(bleu,255);
    delay(i);
    analogWrite(rouge,0);
    analogWrite(vert,0);
    analogWrite(bleu,0);
    delay(i);
  }
  delay(10);
}
Il y a donc 3 modes : un mode avec une led UV, un mode couleur aléatoire (avec une variable "n" à ajuster pour régler le nombre de clignotement d'une même couleur) et un mode couleur fixe (ajustable avec un potentiomètre).
Quelque soit le mode, on peut faire varier la fréquence clignotement des LED (grâce à la variable "i").
L'histoire du booléen bien sûr que ça fonctionne, mais ça dépend de ce que tu veux faire de ton programme. L'idée c'est d'avoir une variable dont la valeur est "vrai" ou "faux", rien d'autre. A chaque passage dans la boucle principale, elle change de valeur (si elle était vraie, elle devient fausse, et inversement).

Et dans ta boucle tu évalues cette variable : Si elle est fausse tu éteins les LEDs (0,0,0), si elle est vraie, tu fais ton programme normal avec choix des couleurs en fonction de ce que tu veux.

Comme ça, un passage de boucle sur deux sera coloré, et un passage de boucle sur deux sera éteint. Bien sûr, faut pas que la boucle soit trop rapide sinon tu verras qu'une LED allumée (une LED qui s'éteint puis s'allume à haute fréquence, notre oeil la voit toujours allumée). Donc faut mettre le bon delay() à la fin de ta boucle, par exemple 200ms voire 500ms.

Cette technique du booléen c'est un schéma qui est énormément reproduit en programmation, ça se fait beaucoup. C'est l'un des moyens les plus simples et rapide pour avoir quelque chose qui switch entre deux états à chaque passage d'une boucle.
Ah ok d'accord. Je voyais pas où tu voulais en venir et ce que ça permettait de réaliser en fait. Merci pour les explications.

@ds-black : en pull down c'est à dire ?
le pull down et pull up en image http://fr.wikipedia.org/wiki/R%C3%A9sistance_de_rappel
l'exemple de wikipedia est en pull up dans ton cas il faut cablé ta résistance a la masse et ton switch au 5V.

un exemple de code qui illustre la var boolean
Code:
  long temps = millis();
  boolean clignotant = false;
     if(millis() - temps > 250)
    {
      clignotant = !clignotant
      digitalWrite(led[ROUGE], clignotant);
      temps = millis();
    }
la fonction millis() donne le temps de fonctionnement depuis le dernier reset ou démarrage de l'arduino. l'avantage c'est que tu ne bloque pas l'exécution du prog comme avec un delay().

une dernière petite chose pour simplifier ton prog n = n + 1 tu peux écrire a la place n++ et n-- pour decrémenter

et c'était le chéri de ds-black au clavier
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés