Arduino Forum

International => Français => Topic started by: MoneGr0s on Jul 16, 2013, 09:04 pm

Title: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 16, 2013, 09:04 pm
Bonjour à tous,

Je débute avec Arduino et je viens de commander tout le matériel nécessaire pour bien démarrer :)
Je n'ai encore rien reçu, mais pour me mettre dans le bain je regarde un peu tout ce qui se fait.

Je vais recevoir un afficheur LCD 4x20 et un Arduino UNO R3.

Je voulais simplement savoir si il existe un façon d'afficher à l'écran un menu, avec des choix à valider, SANS interrompre une séquence d'automatismes.

Admettons que dans mon loop j'ai un fonction qui fasse qu'une LED s'allume et s'éteint toutes les deux secondes.
Est-ce que je vais pouvoir créer un menu pour choisir l'intervalle ou la LED s'éteint, sans qu'elle s'arrête de clignoter ?

Je sais pas si ma demande est claire, mais vu que tout est dans un loop, j'ai du mal à saisir comment je peux afficher du texte à l'écran, et en même temps exécuter le code qui fait clignoter la LED.

Je suis vraiment débutant, et je vais mettre beaucoup de temps à apprendre comment on utilise la librairie menu, mais pour une question de logique, je voudrais avoir la réponse à cette question.

Merci pour vos lumières !
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: B@tto on Jul 16, 2013, 09:15 pm
L'arduino n'est pas multi-tâche au sens pur du terme mais on peut s'en rapporcher ;)

http://battomicro.wordpress.com/2013/06/07/tutorial-les-interruptions-temporelles-avec-arduino/
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 16, 2013, 09:35 pm
Merci pour cette réponse rapide qui me donne un nouvel élément dans ma quête :D

Cet exemple montre qu'on peut faire blinker une LED sans utiliser Delay, en comparant le temps écoulé par rapport à un point de départ, mais je ne saisi toujours pas comment on peut utiliser autre chose, en même temps ^^

Pour être un peu plus précis, je souhaiterai pouvoir commander grâce à un relais, divers appareils pour gérer automatiquement la température et l'hygrométrie.

Dans mon code je stipulerai que Si la température excède 20°, le ventilateur s'allume,
Et à la suite, Si l'hygrométrie chute sous 20%, le brumisateur s'allume (le code sera bien plus complet mais ça donne une idée)

Est-ce qu'il me sera possible d'accéder à un menu de réglages affiché sur LCD, me proposant de modifier les seuils de températures, tout en continuant ces mêmes vérifications qui gèrent les appareils connectés au relais ?
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: Christian_R on Jul 17, 2013, 12:08 am
Le temps d'exécution d'un affichage à l'écran est minuscule.
On peut alterner rapidement plusieurs tâches différentes en donnant l'impression d'être multitâche.

1) afficher ou actualiser le menu, puis
2) mesurer la température, puis
3) mesurer l'hygrométrie, puis
4) agir sur les actionneurs selon T, hygro (allumer le ventilo, le brumisateur, etc.)
5) lire l'état des boutons
6) repasser en 1 en boucle
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 08:14 am
Merci christian pour ta réponse.

Donc chaque affichage à l'écran devra être dans une boucle, et contenir toutes les vérifs systématiquement, avec un switch case qui me permet de changer de boucle avec un goto, pour afficher autre chose à l'écran quand j'appuie sur un bouton c'est ça ?

Exemple :

Code: [Select]
SettingsPage1; //Nommage de la boucle
for(;;){ //Boucle 1 :Affichage des options du menu : Page 1
lcd.print ... //Affichage de la chaine de caractère
if(t > extracteur_on) {
  digitalWrite (brasseur, HIGH);
}

switch (var) { // début de la structure
    case 1: // cas 1
      if(Button1 == HIGH){
      goto SettingsPage2;
   
    case 2: // cas 2 etc.....
  }
}


Ce code doit être bourré de fautes étant donné que je n'ai jamais développé et que je n'ai pas encore reçu mon arduino, mais c'est juste pour voir si j'ai la bonne logique. Si par la même occasion vous pouviez m'expliquer les erreurs commises ce bout de code me servira très certainement.

Merci beaucoup !
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: skizoh on Jul 17, 2013, 10:49 am
C'est pas si mal fait juste attention avec les goto ^^' en informatique on nous apprend souvent qu'un goto c'est le mal  ]:D

Enfin après c'est utilisable mais bon c'est controversé, quand on à du mal à codé ça aide à très vite ce perdre, si c'est pas ton cas, enjoye  :smiley-mr-green:

Donc à utiliser avec parcimonie :)

Skizo !
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 11:05 am
Merci Skizoh !

Dans le bout de code j'ai fait aucune erreur ?  :smiley-eek:

Pour le goto j'avais déjà lu que les développeurs aimaient pas ça. Une fois j'avais fait un script batch gigantesque, avec des goto de partout, et j'arrivais à gérer. Mais si c'est pas très propre, par quoi je peux bien les remplacer dans mon cas ? Pour sortir d'une boucle et me rendre à un autre endroit, qui ne se trouverais pas juste en dessous dans le code...
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MiGaNuTs on Jul 17, 2013, 02:07 pm
Pour faire croire que ton arduino fait  plusieurs choses en même temps, il faut te rapprocher du fonctionnement d'un automate.

Dans ton loop() tu ne doit jamais bloquer ton programme, ou tout du moins le bloquer le moins longtemps possible, et mémoriser des états

A chaque passage dans le loop les différentes actions sont conditionnées aux états mémorisés et tes entrées.
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: skizoh on Jul 17, 2013, 02:14 pm
tu mets un flag à 1 et quand tu passe à l'endroit voulu tu test ce flag et pour sortir de la boucle un break; fera l'affaire :)

Et non je crois pas que tu ai fait d'erreur sinon :)
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 02:56 pm
Merci pour vos infos,

est-ce que quand je fais un switch case dans une boucle infinie le code la réponse des boutons pour boucler ?
Ou alors il boucle à l'infini jusqu'à ce qu'un bouton soit enclenché ?

Il y a une chose aussi que j'ai du mal à comprendre, c'est que selon l'endroit ou on poste une interaction avec un bouton poussoir dans une boucle, il se peut que quand on appuis sur le bp, il ne passe rien si le code n'en est pas à cet endroit, et qu'il faille laisser appuyer sur le bp jusqu'a ce que le code lise son état. Y a t'il une solution contre ça ? Ou il faut simplement bien calculer son coup ?

EDIT : Skizoh a répondu pendant que j'écrivais ce message. Je n'ai pas bien compris ton dernier message, à part le break; pour sortir.
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MiGaNuTs on Jul 17, 2013, 03:53 pm
Si ton programme est bien fait, ton temps de cycle est plus court que la vitesse a laquelle tes yeux voient le monde.

Pense tu que c'est si important que ça que ton programme soit pile poil sur le if qui teste l'état de ton bouton au moment ou tu appuie dessus, ou bien ca ne changera rien s'il est a la ligne d'après (cas le plus défavorable) et que ton programme refait un tour avant de réagir ?
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: skizoh on Jul 17, 2013, 04:25 pm
Bon pour faire simple le temps que tu appuie sur le bouton ( à par pour les énormeeeeeeeeee programme !!!!!! ) ton prog auras déjà fait 3 tour voir 30, donc ne t'en fait pas tu auras à peine relâcher que le prog aura déjà mis le flag à 1 refait un tour pour tomber sur la zone à traiter, la traiter et l'afficher xD

Soit pas si inquiet on est loin des 50hz du début de l'électronique, le temps de réaction sera minime :)
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 04:43 pm
OK OK :)

Bon et bien merci pour vos réponses à mes questions !!! :D

Vivement que je reçoive tout le matériel pour commencer à appliquer les tutoriels de base !

Je vais commencer par le classique "HELLO WORLD", faut bien commencer par quelque part !

Merci encore pour ces explications théoriques, j'y voit plus clair maintenant.

ah et dernière question, est-ce que je peux afficher mon menu réglages dans la partie void setup(); du code, et y accéder n'importe quand avec un goto, même si je suis dans le void loop(); ?

Code: [Select]

Suite logique boitier de controle :

void setup();{ // C'est ici que sera stocké le menu de réglage ainsi que toutes les autres options.
Affichage Splashcreen //Pour le premier allumage de l'appareil, ou après débranchement.

goto LOOP //Pour sauter le menu des réglages au premier lancement et utiliser les valeurs par défaut

Settings1; //On y accède en appuyant sur le bouton OK à tout moment dans le loop
//On affiche une page différente pour chaque placement de curseur.
MENU DES REGLAGES :
> HORAIRES LAMPES
  EXTRACTION
  BRUMISATEUR
//On lance toutes les vérifs avec les valeurs par défaut pour ne pas arrêter le code pendant l'affichage du menu
Si t > extraction_ON etc...

//On vérifie l'état des boutons :
Si bouton_OK est enfoncé, on va à Settings_horaires
Si bouton_BACK est enfoncé, on va à LOOP //Pour annuler les réglages et reprendre la boucle
Si bouton_DOWN est enfoncé, on va à Settings2 //Pour placer le curseur sur le choix du dessous
Si ça fait 5 secondes qu'il ne s'est rien passé, on va à LOOP //On reprends le cycle normal

Settings2; //Page 2 des réglages
//On affiche une page différente pour chaque placement de curseur.
MENU DES REGLAGES :
  HORAIRES LAMPES
> EXTRACTION
  BRUMISATEUR
//On lance toutes les vérifs avec les valeurs par défaut pour ne pas arrêter le code pendant l'affichage du menu
Si t > extraction_ON etc...

//On vérifie l'état des boutons :
Si bouton_OK est enfoncé, on va à Settings_horaires
Si bouton_BACK est enfoncé, on va à LOOP //Pour annuler les réglages et reprendre la boucle
Si bouton_DOWN est enfoncé, on va à Settings2 //Pour placer le curseur sur le choix du dessous
Si ça fait 5 secondes qu'il ne s'est rien passé, on va à LOOP //On reprends le cycle normal

etc etc...
} //Fin de la partie setup


LOOP; //Les goto renverront ici pour sortir du menu réglage
void loop();//démarrage de la boucle infinie

//On lance toutes les vérifs avec les valeurs par défaut pour ne pas arrêter le code pendant l'affichage du menu
Si t > extraction_ON etc...

Si bouton_OK est enfoncé, on va à Settings1 //TOUT EN HAUT DU CODE !

}//fin de la boucle
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MiGaNuTs on Jul 17, 2013, 06:11 pm
La fonction setup() n'est executée qu'une seule fois, au démarrage de l'arduino.
Comme son nom l'indique, elle doit te servir uniquement a régler pleins de trucs, comme les réglages matériels et aussi l'état initial de tes variables, flags et autres.

Ensuite c'est ta fonction loop() qui tourne en boucle, le plus rapidement possible pour donner l'impression que tout se fait en meme temps.


Les GOTO c'est le mal. Considère que tu doit t'infliger une baffe a chaque fois que ton programme passe par un goto. (méfie toi, a 16 Mhz, ca fait vraiment beaucoup de baffes !)
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 07:45 pm
MDR ca va faire beaucoup de claques en effet !

Donc avec un GOTO, je ne peux pas remonter au dessus de void loop(); ? Ou c'est simplement mal vu par les devs ?

Dans tous les cas, ça revient au même si je met mon menu au tout début de void loop; donc question con ^^ Mais jvoudrais quand même savoir :)

Si dans mon code j'ai uniquement void setup(); et void loop(); comme fonction qui portent un nom, il me suffit d'écrire "GOTO setup" dans le code pour arriver à void setup(); ou il me manque quelque chose ?

Si le GOTO c'est tant le mal que ça, comment je peux créer un menu "momentané" avec plusieurs pages sans GOTO ? J'ai bien peur que ça dépasse mes compétences pour le moment...
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: jfs on Jul 17, 2013, 07:51 pm
Utilise une machine d'état, comme expliqué par Barbudor dans la section tuto.
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 08:10 pm
Les deux topics de Barbudor dans la section tuto ne font pas références à ça... A moins qu'il les ai posté dans la section anglais.
Je vais faire une recherche au sujet de "machine d'état".

Merci.
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MiGaNuTs on Jul 17, 2013, 08:13 pm

MDR ca va faire beaucoup de claques en effet !

Donc avec un GOTO, je ne peux pas remonter au dessus de void loop(); ? Ou c'est simplement mal vu par les devs ?

quand la fonction loop() est terminée, elle reprends automatiquement au début.
Au pire tu peut coller un break ou un return (a tester) pour forcer la fin d'une boucle, mais normalement tu n'en a pas besoin.


Dans tous les cas, ça revient au même si je met mon menu au tout début de void loop; donc question con ^^ Mais jvoudrais quand même savoir :)



Si dans mon code j'ai uniquement void setup(); et void loop(); comme fonction qui portent un nom,


Rien ne t'empêche de créer d'autres fonctions pour faire différents trucs. En fait les fonctions c'est un des principes du C. Tout est fonction.


il me suffit d'écrire "GOTO setup" dans le code pour arriver à void setup(); ou il me manque quelque chose ?

PAS DE GOTO ! (je me repete on dirais ^^)

qd ta fonction setup() est terminée, l'arduino va tout seul dans la fonction loop(). Tu n'a pas a te prendre la tete avec ca.

ta fonction setup() ne doit être exécutée qu'une seule fois !


Si le GOTO c'est tant le mal que ça, comment je peux créer un menu "momentané" avec plusieurs pages sans GOTO ?


en combinant machine a état et fonction personnalisées.


J'ai bien peur que ça dépasse mes compétences pour le moment...


Je te conseille d'aller faire un tour sur "le site du zero" et d'apprendre les bases du C.
Certes sr un ordinateur c'est un peu différent de sur l'arduino, mais les principes sont les mêmes.
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 08:27 pm
J'ai du mal à trouver des infos précises pour débutant concernant cette fameuse machine à état :)

Il s'agit en fait d'un switch case amélioré ?
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: papybricol on Jul 17, 2013, 09:13 pm
Bonsoir,

les goto c'est bon pour les marchands d'aspirine, (sauf si ton code est très court)


Code: [Select]
void setup()
    {......
     menu();
     ......
    }
void loop()
    {......
     if (bouton....)
         {menu();
         }
      .......
     }
void menu()
    {......
     ......
     }


Résultat du sondage: pas beaucoup de partisans du GOTO, doit y avoir une raison,
Quant à moi,  j'ai plus de raison de faire plaisir à mes profs....pourtant jamais de GOTO 
Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: jfs on Jul 17, 2013, 09:39 pm

J'ai du mal à trouver des infos précises pour débutant concernant cette fameuse machine à état :)

Il s'agit en fait d'un switch case amélioré ?


J'ai retrouvé le message de Barbudor :


Appelé aussi "Machine d'état"

Code: [Select]
enum { WAIT_CONNECT, WAIT_LOGIN, WAIT_PASSWORD, RUNNING } Etat;

void loop()
{
  switch( Etat )
  {
  case WAIT_CONNECT:
    //... ici le code pour se connecter au serveur telnet
    // et quand connecté :
    Etat = WAIT_LOGIN;
    break;
  case WAIT_LOGIN:
    // ... ici le code pour attendre "login:"
    // et quand reçu "login:"
    // envoyer le login puis
    Etat = WAIT_PASSWORD;
    break
... etc , je suis trop fainéant pour continuer
}


Sans oublier la gestion des cas d'erreurs tels que timeout, deconnection, etc ....

Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MoneGr0s on Jul 17, 2013, 11:12 pm
Merci pour les infos.

Donc si j'ai bien compris dans un premier temps je dois énumérer chaque page de mon menu :
Code: [Select]

enum { Settings_1, Settings_2, Settings_3 } Etat;


Chaque page sera en fait un "Etat"

Et ensuite je fais un switch case avec la variable "Etat", et chaque case m'affichera une nouvelle page de LCD ?
Dans le cas d'un menu multi-choix il faudra que je mette quelque chose de ce style ?

Code: [Select]

case Settings_1:
lcd.print("MENU REGLAGES")
lcd.print("> Réglage 1")
lcd.print("  Réglage 2")
if (bouton_OK == HIGH){
  Etat = Settings_2;
  }

if (bouton_DOWN == HIGH){
  Etat = Settings_3;
  }

Break;


Title: Re: Afficher un menu sur LCD sans intérrompre le reste du code ?
Post by: MiGaNuTs on Jul 18, 2013, 11:11 pm
Ca peut ressembler a ca.

Commence par faire des p'tits dessins (ordinogrames ou trucs du genre) de comment doit se comporter ton programme, ca te facilitera la tache.