Modifications

Sauter à la navigation Sauter à la recherche
8 567 octets ajoutés ,  15 février 2016 à 11:24
Ligne 14 : Ligne 14 :  
# Attendre deux secondes après avoir changé l'état de la LED(4)
 
# Attendre deux secondes après avoir changé l'état de la LED(4)
 
# Allumer la LED(2) pendant le temps d'attente.
 
# Allumer la LED(2) pendant le temps d'attente.
}}
      
[[Fichier:PyBoard-LEDs.jpg|480px]]
 
[[Fichier:PyBoard-LEDs.jpg|480px]]
 +
 +
Comme j'ai travaillé comme ''un cochon'', j'ai introduis pas mal d'erreur dans mon bout de code, ce fut l'occasion de me pencher sur les méthodes de débogage... puis de la rédaction de ce tutoriel.}}
    
== Débogage à l'ancienne ==
 
== Débogage à l'ancienne ==
 
{{bloc-etroit|text=C'est les vieilles méthodes qui marchent le mieux!
 
{{bloc-etroit|text=C'est les vieilles méthodes qui marchent le mieux!
   −
Au tout début de la programmation, il suffisait d'afficher des messages à l'écran (un peu partout), cela permettait de déterminer la partie du code qui fonctionne et donc d'approcher par étape successive la partie du code qui était problèmatique.
+
Au tout début de la programmation, il suffisait d'afficher des messages à l'écran (un peu partout), cela permettait de déterminer la partie du code qui fonctionne et donc d'approcher par étapes successives la partie du code qui était problématique.
    
C'est bien beau tout cela mais sur la PyBoard, il n'y a pas d'écran! '''Mais nous avons néanmoins 4 LEDs utilisateurs'''.}}
 
C'est bien beau tout cela mais sur la PyBoard, il n'y a pas d'écran! '''Mais nous avons néanmoins 4 LEDs utilisateurs'''.}}
Ligne 53 : Ligne 54 :  
     pyb.LED(2).on()
 
     pyb.LED(2).on()
 
     delay(2000)
 
     delay(2000)
     pyb.LED(2).off()
+
     pyb.LED(2).off()</nowiki>
</nowiki>
   
   
 
   
 
Notez les instructions '''pyb.LED(2).on()''' et '''pyb.LED(2).off()''' qui me permettent de savoir quand le programme cycle.
 
Notez les instructions '''pyb.LED(2).on()''' et '''pyb.LED(2).off()''' qui me permettent de savoir quand le programme cycle.
Ligne 97 : Ligne 97 :  
Je sauve mon programme, j'éjecte le disque Flash de ma PyBoard, je presse le bouton Reset.
 
Je sauve mon programme, j'éjecte le disque Flash de ma PyBoard, je presse le bouton Reset.
   −
J'ouvre alors un terminal sur la Pyboard avec Pytty (voyez l'article [[MicroPython-Hack-REPL|invite REPL]] pour plus d'information).
+
J'ouvre alors un terminal sur la Pyboard avec Pytty ou Screen (voyez l'article [[MicroPython-Hack-REPL|invite REPL]] pour plus d'information).
    
Voici ce que j'y ai vu une fois le bouton X4 enfoncé...
 
Voici ce que j'y ai vu une fois le bouton X4 enfoncé...
    +
[[Fichier:MicroPython-HAck-Debug-01.jpg|560px]]
 +
 +
Nous pouvons clairement voir:
 +
# Un monstrueux message d'erreur (mais nous y reviendrons juste ci-dessous).
 +
# Les différents messages '''print()''' envoyés par la PyBoard sur le terminal.
 +
# Le message ''attendre pression bouton'' ne s'y retrouve pas<br />''Normal, ce message a été envoyé dès le démarrage du programme... bien avant que j'ai eu le temps de démarrer '''screen''' ou '''putty''' pour voir les message''
 +
 +
== Détecter les erreurs de compilation ==
 +
 +
Ce fût le cas dans mon script ci-dessus... j'ai une horrible erreur de compilation qu'il m'aura fallut bien du temps à identifier.
 +
 +
Sans l'utilisation d'un terminal, je n'aurais probablement pas identifier cette source d'erreur.
 +
 +
[[Fichier:MicroPython-HAck-Debug-01.jpg|560px]]
 +
 +
{{ambox-stop|text=Le terminal est un outil ''quasi'' indispensable pour détecter les erreurs dans les scripts!}}
 +
 +
Le message est sans équivoque, il ne sait pas appeler la fonction '''delay()'''. J'avais oublié le nom du module '''pyb'''... l'instruction correcte est {{fname|pyb.delay(2000)}}.
 +
 +
=== La version corrigée ===
 +
<nowiki>import pyb
 +
 +
def wait_pin_change(pin):
 +
    # attendre que la broche change de valeur
 +
    cur_value = pin.value()
 +
    # Elle doit être stable pendant un temps continu de 20ms
 +
    active = 0
 +
    while active < 20:
 +
        if pin.value() != cur_value:
 +
            active += 1
 +
        else:
 +
            active = 0
 +
        pyb.delay(1)
 +
 +
pin_x4 = pyb.Pin('X4', pyb.Pin.IN, pyb.Pin.PULL_DOWN)
 +
while True:
 +
    print( 'attendre pression bouton' )
 +
    wait_pin_change(pin_x4)
 +
    print( 'bouton enfonce' )
 +
    pyb.LED(4).toggle()
 +
    print( 'LED modifiee' )
 +
    pyb.LED(2).on()
 +
    print( 'LED 2 allumee')
 +
    pyb.delay(2000)
 +
    pyb.LED(2).off()
 +
    print( 'LED 2 eteinte')</nowiki>
 +
 +
== Attendre pour déboguer ==
 +
Nous avons vu que l'utilisation d'un terminal série et des instructions '''print()''' sont bien utiles pour déboguer un programme.
 +
 +
Par contre, le programme dans {{fname|main.py}} est exécuté immédiatement... peut être trop vite pour avoir le temps de lancer un programme terminal et voir les premiers {{fname|print()}}.
 +
 +
La petite astuce, c'est d'attendre que l'utilisateur presse le bouton USR (''Utilisateur'') de la carte PyBoard pour lancer le programme. 
 +
 +
Voici donc une première version de {{fname|debug_wait_start()}}, cette fonction:
 +
* Est appelée en tout début de programme.
 +
* debug_wait_start():
 +
** Allume la LED(4), bleue, pour signaler que la fonction attend la pression du bouton USR<br />C'est maintenant qu'il faut ouvrir votre session terminal ;-)
 +
** Attend la pression du bouton USR
 +
** Eteind la LED(4) pour signaler que la fonction {{fname|debug_wait_start()}} s'achève.
 +
** Fait un premier {{fname|print()}} avec le message "PROGRAMME STARTED" (ou similaire).
 +
 +
<nowiki># main.py -- put your code here!
 +
 +
import pyb
 +
 +
def wait_pin_change(pin):
 +
    # attendre que la broche change de valeur
 +
    cur_value = pin.value()
 +
    # Elle doit être stable pendant un temps continu de 20ms
 +
    active = 0
 +
    while active < 20:
 +
        if pin.value() != cur_value:
 +
            active += 1
 +
        else:
 +
            active = 0
 +
        pyb.delay(1)
 +
 +
def wait_user_button():
 +
    pin_user = pyb.Pin('X17', pyb.Pin.IN, pyb.Pin.PULL_UP)
 +
    wait_pin_change( pin_user )
 +
 +
 +
def debug_wait_start():
 +
    print( 'PRESS USR TO START' )
 +
    # allumer la LED bleue
 +
    pyb.LED(4).on()
 +
    # attendre la pression du bouton user
 +
    wait_user_button()
 +
    # eteindre LED bleue
 +
    pyb.LED(4).off()
 +
    # Informer l'utilisateur
 +
    print( 'PROGRAMME STARTED' )
 +
 +
 +
debug_wait_start()
 +
pin_x4 = pyb.Pin('X4', pyb.Pin.IN, pyb.Pin.PULL_DOWN)
 +
while True:
 +
    print( 'attendre pression bouton' )
 +
    wait_pin_change(pin_x4)
 +
    print( 'bouton enfonce' )
 +
    pyb.LED(4).toggle()
 +
    print( 'LED modifiee' )
 +
    pyb.LED(2).on()
 +
    print( 'LED 2 allumee')
 +
    pyb.delay(2000)
 +
    pyb.LED(2).off()
 +
    print( 'LED 2 eteinte')</nowiki>
 +
 +
== Controle+C et Controle+D ==
 +
Nous l'avons vu plus haut, l'utilisation d'un terminal est bien pratique pour détecter les erreurs mais il se sera aussi pour modifier et redémarrer votre programme sans devoir éjecter et réinitialiser la carte.
 +
 +
{{ambox|text=Le terminal vous permettra d'arrêter, modifier et redémarrer votre programme sans réinitialiser la carte ;-) }}
 +
 +
nous allons créer un bouton à deux états qui contrôle la LED(2) (presser une fois pour allumer, une autre fois pour éteindre).
 +
 +
{{FImage|MicroPython-Hack-deboucing.jpg|480px}}
 +
 +
Le programme utilise la méthode décrite précédemment pour attendre la pression du bouton utilisateur avant de démarrer.
 +
 +
Connectez votre PyBoard sur votre ordinateur... vous pourrez ainsi modifier le fichier {{fname|main.py}} de la carte.
 +
 +
Nous vous proposons de copier le code suivant, sauvez le fichier... puis de lire la suite de l'article.
 +
 +
<nowiki># main.py -- put your code here!
 +
 +
import pyb
 +
 +
 +
def wait_pin_change(pin):
 +
    # attendre que la broche change de valeur
 +
    cur_value = pin.value()
 +
    # Elle doit être stable pendant un temps continu de 20ms
 +
    active = 0
 +
    while active < 20:
 +
        if pin.value() != cur_value:
 +
            active += 1
 +
        else:
 +
            active = 0
 +
        pyb.delay(1)
 +
 +
def wait_user_button():
 +
    pin_user = pyb.Pin('X17', pyb.Pin.IN, pyb.Pin.PULL_UP)
 +
    wait_pin_change( pin_user )
 +
 +
 +
def debug_wait_start():
 +
    print( 'PRESS USR TO START' )
 +
    # allumer la LED bleue
 +
    pyb.LED(4).on()
 +
    # attendre la pression du bouton user
 +
    wait_user_button()
 +
    # eteindre LED bleue
 +
    pyb.LED(4).off()
 +
    # Informer l'utilisateur
 +
    print( 'PROGRAMME STARTED :-)' )
 +
 +
 +
debug_wait_start()
 +
pin_x1 = pyb.Pin('X1', pyb.Pin.IN, pyb.Pin.PULL_DOWN)
 +
current_state = 0 # dernier état connu de la broche X1
 +
bascule = 0 # Variable qui change d etat a chaque fois que l'on pousse le bouton
 +
 +
while True:
 +
    # lecture des entrees
 +
    val1 = pin_x1.value()
 +
 +
    # déparasitage logiciel
 +
    pyb.delay(10) # Attendre 10 millisecondes
 +
 +
    # relecture des entrées
 +
    val2 = pin_x1.value()
 +
 +
    # Si val1=Val2 --> Etat Stable
 +
    if val1 == val2:
 +
        # Si valeur lue différente de l'état connu
 +
        if val1 != current_state:
 +
          # On memorise l'etat du bouton comme etat connu
 +
          current_state = val1
 +
          # Bien entendu, le programme ne doit agir que lorsque le bouton
 +
          # est enfoncé (par lorsqu'il est relaché)
 +
          if val1 == 1:
 +
              print( 'bascule before %i' % bascule )
 +
              # On inverse l'état de la "bascule"
 +
              bascule = 0 if bascule == 1 else 1
 +
              print( 'bascule after %i' % bascule )
 +
              # Apliquer l'etat de la bascule sur la LED(2)
 +
              if bascule == 1:
 +
                  pyb.LED(2).on()
 +
              else:
 +
                  pyb.LED(2).off()
 +
 +
    # exécuter le reste du programme</nowiki>
 +
 +
Sauvez le fichier main.py sur la PyBoard. Gardez votre éditeur de texte ouvert... nous allons faire quelque-chose de magique.
 +
 +
Maintenant, rendez-vous dans le terminal (celui que vous avez ouvert pour vous connecter sur la PyBoard).
 +
 +
A l'invite de commande REPL, pressez la combinaison de touche CTRL+D. Cela à pour effet de faire un SOFT REBOOT de votre PyBoard.
 +
 +
 +
Ce qu'il y a de génial avec le Soft Reboot:
 +
# Le lecteur Flash de la PyBoard reste connecté.
 +
# Le programme {{fname|main.py}} est compilé et démarré.
 +
 +
[[Fichier:micro-python-hack-debug-soft-reboot.jpg]]
 +
 +
Comme vous pouvez le voir, le programme {{fname|main.py}} a bien été démarré au Soft Reboot et nous avons même fait quelques opérations.
 +
 +
Maintenant, pressez CTRL+C dans le terminal pour arrêter le programme.
 +
 +
[[Fichier:micro-python-hack-debug-halt-program.jpg]]
 +
 +
Je vous propose maintenant de modifier le programme {{fname|main.py}} (normalement toujours ouvert dans votre éditeur de texte favori).
 +
 +
Modifiez la ligne suivante:
 +
 +
<nowiki>print( 'PROGRAMME STARTED :-)' )</nowiki>
 +
 +
en
 +
 +
<nowiki>print( 'Allez HOP! c est parti...' )</nowiki>
 +
 +
Sauvez votre votre modification,
 +
 +
Rendez-vous dans votre terminal et pressez la combinaison de touche CTRL+D pour faire un Soft Reboot.
 +
 +
Pressez ensuite le bouton utilisateur (USR) et regardez la magie opérer...
 +
 +
Notre modification est prise en compte :-)
 +
 +
[[Fichier:micro-python-hack-debug-soft-reboot2.jpg]]
 +
 +
Ce n'est pas génial ça?
 +
 
{{MicroPython-Hack-Debug-TRAILER}}
 
{{MicroPython-Hack-Debug-TRAILER}}
29 836

modifications

Menu de navigation