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 // ... |
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) |
Code bash : | Sélectionner tout |
sudo minicom -b 115200 -o -D /dev/ttyACM0
Exemple de compte-rendu dans un terminal minicom :