IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Raspberry Pi Pico - Entrées numériques, communication série USB, et gestion du temps,
Un billet blog de f-leb

Le , par f-leb

0PARTAGES

Entrées numériques, communication série USB, et gestion du temps... tout ça en un seul billet, mais dans cette série sur le SDK C/C++ pour Raspberry Pi Pico, on cherche justement à découvrir rapidement.

Pour expérimenter les entrées numériques, on câblera un bouton-poussoir à appui momentané, à raccorder à la broche GP8 et la broche d'alimentation 3V3, comme sur le schéma ci-dessous :


Le but est de détecter un appui « long », disons le bouton maintenu pendant au moins 1 seconde. On aura donc besoin de mesurer le temps écoulé entre la détection de l'appui et le moment du relâchement du bouton.
Et pour rendre compte de la situation, on mettra en œuvre un retour de messages par le câble USB pour affichage dans un terminal (à la façon du Terminal Série dans l'EDI Arduino).
Le décor est planté...

Gestion des entrées numériques

Pour configurer une broche en entrée, vous pouvez écrire la séquence :
Code C : Sélectionner tout
1
2
gpio_set_function(pin_number, GPIO_FUNC_SIO); 
gpio_set_dir(pin_number, GPIO_IN);

Vous pouvez alors activer la résistance interne de rappel (pull-down) ou la résistance de tirage (pull-up) (entre 50 et 80kΩ) :
Code C : Sélectionner tout
1
2
gpio_pull_down(pin_number); 
gpio_pull_up(pin_number);

Et finalement, pour relever l'état de l'entrée :
Code C : Sélectionner tout
bool state = gpio_get(pin_number);

Gestion du temps

Le SDK offre de nombreuses fonctions d'horodatage (timestamp) et de temporisation (sleep).

On retiendra la fonction sleep_us(uint64_t us) pour suspendre l'exécution pendant un temps exprimé en microsecondes (10-6 secondes).

Pour l'horodatage, il existe bien une fonction time_us_64() qui renvoie en entier uint64_t le temps écoulé en microsecondes depuis la mise en alimentation, mais le kit propose un type absolute_time_t et des fonctions associées lorsque les temps exprimés sont des temps absolus d'horodatage, et non des durées relatives (à exprimer en entier uint64_t).
Par exemple, avec le code :
Code C : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  // ... 
  
  absolute_time_t start = get_absolute_time(); // start = représentation de l'instant courant 
  absolute_time_t end = delayed_by_ms(start, 10); // end = start + 10 millisecondes 
  
  // Autres actions ici... 	 
  
  sleep_until(end); // suspendre jusqu'à expiration des 10 ms 
  
  // ...
On comprend que la durée des traitements dans ce bloc de code sera de 10 ms au minimum, et que si les « autres actions ici » prennent moins de 10 ms de temps, le programme patientera un peu à la ligne sleep_until(end) en attendant que ces 10 ms soient écoulées. La technique est intéressante dans une boucle de scrutation qui doit reprendre à intervalles réguliers.

Et si on veut calculer une durée (en microsecondes) entre deux instants, on utilisera :
Code C : Sélectionner tout
uint64_t diff = absolute_time_diff_us(absolute_time_t from, absolute_time_t to);

Communication série USB

Une version de la bibliothèque stdio a été prévue pour gérer les entrées-sorties standards de la Raspberry Pi Pico, et on peut s'en servir pour envoyer ou recevoir des messages par un port série UART ou par un port USB. C'est là que la fonction d'affichage de messages formatés printf() vient à notre rescousse pour rendre compte dans un terminal Série.
Avant d'utiliser printf(), il faut initialiser les E/S avec stdio_init_all(). Dans le fichier de configuration cmake (CMakeLists.txt), on rajoutera une ligne pico_enable_stdio_usb(NomDuProjet 1) pour diriger la sortie standard vers l'USB.

Tout est en place pour une démonstration...

Démonstration avec la détection d'un appui long

Dans le code source ci-dessous, on implémente une machine à états finis. Deux états NOT_PUSHED et PUSHED suffisent ici. Quand l'appui est détecté, on relève l'instant de l'appui et l'état passe à PUSHED. Dans ce nouvel état, si le bouton est relâché, on calcule la durée de l'appui et on rend compte dans le terminal série si l'appui est court ou long (> 1 s). La durée de l'appui est affichée dans ce dernier cas, et on revient à l'état initial NOT_PUSHED.

Fichier source pushbutton.c :
Code C : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h> 
#include "pico/stdlib.h" 
  
int main() 
{ 
  stdio_init_all(); 
  
  const uint pinButton = 8; // voir schéma câblage 
  gpio_set_function(pinButton, GPIO_FUNC_SIO); 
  gpio_set_dir(pinButton, GPIO_IN); 
  gpio_pull_down(pinButton); // activation pull-down 
  
  enum state_t {NOT_PUSHED, PUSHED}; 
  enum state_t state = NOT_PUSHED; // état initial 
  
  bool button_pressed; 
  absolute_time_t t, tpush; 
  
  while (true) 
  { 
    button_pressed = gpio_get(pinButton); 
    t = get_absolute_time(); // horodatage 
  
    switch (state) 
    { 
    case NOT_PUSHED:      // état = bouton relâché 
      if (button_pressed) // si bouton pressé 
      { 
        state = PUSHED; 
        tpush = t; 
      } 
      break; 
  
    case PUSHED:           // état = bouton appuyé 
      if (!button_pressed) // si bouton relâché 
      { 
        state = NOT_PUSHED; 
        uint64_t diff = absolute_time_diff_us(tpush, t); // durée de l'appui en us 
        if (diff > 1000000) // si appui long > 1s 
        { 
          printf("Appui long détecté ! (%4.2f s)\n\r", diff / 1000000.); 
        } 
        else 
        { 
          printf("Appui court\n\r"); 
        } 
      } 
      break; 
  
    default: 
      state = NOT_PUSHED; 
    } 
  
    sleep_until(delayed_by_ms(t, 5)); // attendre 5ms entre chaque scrutation de l'entrée 
  } 
}


On donne aussi le fichier de configuration CMake. Pour la génération (build) du projet, voir la méthode dans le 1er billet de la série.

fichier CMakeLists.txt :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cmake_minimum_required(VERSION 3.13) 
 
# initialize the SDK based on PICO_SDK_PATH 
# note: this must happen before project() 
include(pico_sdk_import.cmake) 
 
project(pushbutton) 
 
# initialize the Raspberry Pi Pico SDK 
pico_sdk_init() 
 
 
# rest of your project 
add_executable(pushbutton 
    pushbutton.c 
) 
 
# Add pico_stdlib library which aggregates commonly used features 
target_link_libraries(pushbutton pico_stdlib) 
 
pico_enable_stdio_usb(pushbutton 1) 
pico_enable_stdio_uart(pushbutton 0) 
 
# create map/bin/hex/uf2 file in addition to ELF. 
pico_add_extra_outputs(pushbutton)
J'ai choisi minicom comme terminal Série. Si le nom du port entre le PC et la Raspberry Pi Pico est ttyACM0, on ouvre le terminal avec la commande :
Code bash : Sélectionner tout
sudo minicom -b 115200 -o -D /dev/ttyACM0

Exemple de compte-rendu dans un terminal minicom :

Une erreur dans cette actualité ? Signalez-nous-la !