Changes between Initial Version and Version 1 of IOC20_T01


Ignore:
Timestamp:
Jan 27, 2020, 12:20:54 PM (5 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • IOC20_T01

    v1 v1  
     1= 1. Préambule
     2
     3Au long de ce module, vous allez utiliser 4 nano-ordinateurs :
     4* Raspberry P1 1B
     5* Raspberry PI 3B
     6* Arduino nano
     7* Module ESP32 TTGO-Lora32-Oled
     8
     9Dans ce TP, vous allez :
     10* écrire une application pour la Raspberry Pi 1B pour faire clignoter deux LEDs selon un motif que vous choisirez et également de récupérer les informations d'un bouton poussoir.
     11
     12À la fin de ce TP, vous devriez avoir acquis les compétences suivantes:
     13* Compilation croisée via un compilateur déporté
     14* Contrôle distant de système embarqué par liaison réseau (SSH)
     15* Manipulation d'un périphérique GPIO et de ses registres "memory mappés"
     16* Écriture d’une librairie C pour la manipulation des GPIO.
     17
     18= 2. Hello World! Raspberry PI 1
     19
     20**Plateforme des TP pour les Raspberry Pi**
     21
     22[[Image(htdocs:png/plateforme-peri-raspberry.png, width=700px, nolink)]]
     23
     24Pour exécuter votre programme sur une carte Raspberry Pi, vous devez vous connecter en SSH sur une carte Raspberry Pi en passant par le routeur peri. Le routeur a deux adresses: `132.227.71.43` du coté laboratoire et `192.168.1.1` de l'autre coté.  Le serveur de nom lui a attribué un nom : peri. Le routeur crée un sous-réseau (`192.168.1.x`) où sont connectées les cartes. Les cartes sont numérotées de `20` à `26` plus des cartes étudiants (ici n°30), le routeur a été programmé de telle sorte que l'adresse internet de la carte n°`X` ait comme adresse 192.168.1.`X` (par exemple la carte n°`20` a comme adresse sur ce réseau `192.168.1.20`).
     25Pour faire ça, le firmware du routeur a été remplacé par '''[[http://www.dd-wrt.com/site/index | dd-wrt]]''' qui permet ce type de mode.  Le routeur a été également été programmé pour que tous les paquets entrants sur le port `5000`+`X` de l'adresse peri soient routés vers l'adresse `192.168.1.X`.
     26
     27Il n'y a qu'un seul compte utilisateur sur une carte Raspberry Pi. Le nom de login est `pi` et le mot de passe est `raspberry`.
     28
     29Ainsi, pour se connecter en ssh sur la carte n°`22` avec le login `pi`, il faut taper (remarquez que c'est un `p` minuscule):
     30{{{#!sh
     31$ ssh -p 5022 pi@peri
     32pi@peri's password: raspberry
     33}}}
     34
     35Comme, il n'y a qu'un compte par carte et que vous allez devoir vous les partager, vous devez créer un répertoire à la racine avec le nom de votre login sur le réseau enseignement accolé avec un tiret avec le nom de votre binôme si vous en avez un. Par exemple, deux personnes en binôme se nommant respectivement `almada` et `fomentin` vont créer un répertoire `almada-fomentin` (en minuscule). '''Je vous demande de respecter cette convention afin que je puisse vous identifier facilement.'''
     36
     37Il est recommandé de ne pas laisser de fichiers source sur la carte SD, car celle-ci peut être reformatée en cas de dysfonctionnement.
     38
     39Pour copier un fichier `file.x` depuis votre compte enseignement sur le carte n°`22` il faut taper (remarquez que c'est un `P` majuscule):
     40{{{#!sh
     41$ scp -P 5022 file.x pi@peri:almada-fomentin
     42pi@peri's password: raspberry
     43}}}
     44
     45{{{#!td
     46{{{#!td
     47**__Astuce__**[=#mdp][[BR]]
     48Taper le mot de passe à chaque fois que l'on se logue et à chaque copie peut être pénible à la longue.
     49Pour éviter cela, il faut donner à la !RaspberryPi la clé publique du protocole de chiffrement utilisé pour la connexion.
     50* Pour la première commande, vous devez taper 3 fois sur la touche entrée pour choisir les valeurs par défaut.
     51* Pour la deuxième commande, vous sélectionnez la bonne carte (en remplaçant x par le bon chiffre) et vous tapez le mot de passe `raspberry` (ce sera la dernière fois).
     52* La troisième est là pour vérifier
     53{{{#!sh
     54ssh-keygen -t rsa
     55ssh-copy-id -i $HOME/.ssh/id_rsa.pub -p 502x pi@peri
     56ssh -p 502x pi@peri
     57}}}
     58}}}
     59}}}
     60[[BR]]
     61
     62= 2.1. Prise en mains des outils de développement: Hello World! =
     63
     64La première étape consiste à vous familiariser avec les outils de
     65développement. Pour cela, vous allez développer un petit programme
     66de type "Hello World!" qui affiche une phrase sur la sortie standard
     67grâce à un printf.
     68
     69Pour compiler votre programme, suivez les instructions suivantes.
     70
     71* Tout d'abord, configurez votre terminal pour utiliser le compilateur croisé (vous pourrez ajouter cette commande dans le fichier $HOME/.bashrc):
     72  {{{#!sh
     73  $ source /users/enseig/franck/peri/export_rpi_toolchain.sh
     74  }}}
     75
     76* Une fois le terminal configuré, vérifiez que le compilateur est accessible:
     77  {{{#!sh
     78  $ which bcm2708hardfp-gcc
     79  }}}
     80  Si cette commande ne retourne rien, la configuration n'a pas fonctionné. Appelez le chargé de TP pour vous aider.
     81
     82Votre suite d'outils (toolchain) contient tous les outils nécessaires pour la compilation, l'édition des liens et la manipulation de binaires pour la carte Raspberry Pi. Et tous ces outils sont préfixés par la même chaîne de caractères: `bcm2708hardfp-`. Il s'agit donc d'un compilateur pour un SoC BCM2708 avec l'option hardfp activée (calcul flottant matériel). Il s'agit bien du SoC de la carte Raspberry Pi.
     83
     84Maintenant, pour compiler un programme C vers un binaire qui puisse s'exécuter sur la carte Raspberry Pi, il vous faut écrire un Makefile pour plus de facilité. Pour cela, suivez la syntaxe de base des Makefile:
     85{{{#!make
     86cible: dépendances
     87    commande
     88}}}
     89Notez bien que l'indentation de la seconde ligne doit OBLIGATOIREMENT être une tabulation et non une suite d'espaces.
     90
     91Vous pourrez donc par exemple, écrire la règle de Makefile suivante:
     92{{{#!make
     93helloworld.x: helloworld.c
     94    bcm2708hardfp-gcc -o $@ $< -O2 -static
     95}}}
     96
     97Ci-dessous, un `Makefile` un peu plus complexe qui se charge de la copie et qui utilise la règle de compilation implicite (juste par curiosité). Dans la suite, nous vous fournissons un nouveau Makefile que vous pourrez modifier.
     98
     99{{{#!make
     100CC=bcm2708hardfp-gcc
     101CFLAGS=-O2 -static
     102CARD=20
     103NAME=binome
     104CFLAGS=-W -Wall -Wextra -Wfatal-errors -O2
     105APP=helloworld
     106
     107all: $(APP)
     108    scp -P 50$(CARD) $^ pi@peri:$(NAME)
     109
     110clean:
     111    rm $(APP)
     112}}}
     113
     114  **__Attention__**::
     115  Devant les commandes (scp et rm) vous devez mettre une tabulation. Si vous n'êtes pas familier avec les makefiles, consultez l'article
     116  de [https://fr.wikipedia.org/wiki/Make Wikipedia] ou de [http://gl.developpez.com/tutoriel/outil/makefile/ Developpez.com].
     117
     118  **__0ption -static__**::
     119  L'option "-static" est utilisée par l'éditeur de lien. Elle est importante ici, car la librairie C du compilateur croisé n'est pas tout à fait identique à la librairie C sur la carte Raspberry Pi. Ajouter "-static" à la ligne de compilation permet de créer un binaire qui contient en plus les fonctions de la librairie C utilisée par votre programme. Ceci permettra à celui-ci de ne pas essayer d'utiliser des fonctions de la librairie C installée sur la carte qui, sinon, aurait été chargée dynamiquement.
     120
     121== 2.2. Contrôle de GPIO en sortie ==
     122
     123[[Image(htdocs:png/Raspberry-Pi-GPIO-Layout-Revision-2.png,500px,nolink)]]
     124
     125Dans cet exercice, on vous propose de manipuler une pin du GPIO en mode "sortie" pour contrôler le clignotement d'une LED à une fréquence donnée.
     126
     127* Avant de commencer à écrire du code, déterminez quelles sont les différentes étapes nécessaires depuis l'initialisation jusqu'à l'envoi des valeurs 0 ou 1 sur le GPIO.
     128* Récupérer le répertoire lab1, exécuter la commande suivante dans un terminal et dans le dossier que vous souhaitez pour contenir votre code pour ce premier TP.
     129{{{#!sh
     130cp -rp /users/enseig/franck/peri/lab1 .
     131}}}
     132* Éditez le fichier lab1.c et ajoutez le code que vous pensez nécessaire à la réalisation de cet exercice.\\
     133  ATTENTION: ne changez pas les valeurs de GPIO_LED0, car vous risqueriez d'endommager la carte Raspberry Pi.
     134* Ensuite, compilez-le grâce au Makefile (**Vous devez l'adapter**) qui vous est fourni.
     135  Qu'observez-vous ? Essayez de changer la fréquence de clignotement.
     136
     137{{{#!protected
     138Il faut juste mettre leur nom dans leur Makefile
     139}}}
     140
     141== 2.3. Contrôle de plusieurs GPIO en mode "sortie" ==
     142
     143Refaites le même exercice que précédemment, mais cette fois-ci configurez plusieurs GPIO en sorties.
     144* La LED0 est connectée sur le GPIO 4, **la LED1 est connectée sur le GPIO 17**. Faites clignoter les deux LEDs.
     145* Avant d'exécuter votre programme, vérifiez parce que le matériel est fragile, pour pouvez faire valider votre code avec le chargé de TP.
     146
     147Vous devez faire clignoter les deux LEDs a des fréquences différentes et, si possible, parametrable par des arguments en ligne de commandes.
     148Je vous conseille de créer une thread par LED
     149
     150== 2.4. Lecture de la valeur d'une entrée GPIO ==
     151
     152Maintenant que vous maîtrisez le contrôle d'un GPIO en sortie, passons au mode "entrée".
     153Écrivez un programme qui configure la GPIO 18 en entrée. Vous devez afficher la valeur de ce GPIO dans une boucle infinie.
     154
     155* Une fois réalisé, compilez votre programme comme précédemment à l'aide du Makefile fourni.
     156* Ensuite, copiez votre programme sur la carte comme indiqué dans l'exercice précédent.
     157
     158On veut détecter l'appui sur le bouton poussoir. Pour cela, vous allez lire sa valeur périodiquement toutes les 20ms. L'appui ou le relâchement correspond est présent quand deux valeurs lues successivement sont différentes. Quand le bouton n'est pas enfoncé, la valeur de la broche est à 1. La structure du programme suggéré.
     159{{{#!c
     160val_prec = 1
     161val_nouv = 1
     162BP_ON = 0
     163BP_OFF = 0
     164faire toujours:
     165   attendre 20ms
     166   val_nouv <- valeur du BP
     167   si (val_prec != val_nouv) ET (val_nouv == 0) (appui est detecte) alors BP_ON <- 1
     168   si un relachement est detecte alors BP_OFF <- 1
     169   si BP_ON :
     170      BP_ON <- 0                   // l'appui est un evenement ponctuel
     171      comportement quand un appui est detecte
     172   si BP_OFF :
     173      BP_OFF <- 0                  // Le relachemet est un évènement ponctuel
     174      comportement quand un relachement est detecte
     175}}}
     176
     177Commencer par tester que vous savez détecter l'appui sans gérer les LEDs.
     178
     179Ensuite, faite un programme qui fait clignoter deux fois plus vite les LEDs lorsqu'on appuit sur le bouton une fois, et qui refait clignoter les LEDs normalement au nouvel appui.
     180
     181== 2.5. Réalisation d'une petite librairie ==
     182
     183Écrire les fonctions suivantes et fabriquer une fonction libgpio.a.
     184Vous devez vous même, définir les prototypes des fonctions et écrire le Makefile pour fabriquer une library et linker votre programme avec. Si vous avez des difficultés, Google existe :-)) !
     185
     186Indications : Une bibliothèque de fonction est en principe une archive de fichiers objet (.o). Dans notre cas, c'est un peu particulier, nous n'auront qu'un seul fichier objet à l'intérieur.
     187Cette bibliothèque reçoit l'adresse de base physique des registres GPIO.
     188Elle utilise des variables globale statique (local au fichier) pour stocker des états (file descriptor par exemple).
     189
     190* `int gpio_init(void)`
     191   - Ouverture et mapping
     192   - L'adresse de base des registres GPIO dans l'espace d'adressage physique est supposée connue, mais nous verrons que l'on peut savoir où se trouve les GPIO en lisant des variables exposées par le noyau.
     193   - Rend 0 si pas d'erreur; -1 en cas d'erreur.
     194
     195* `int gpio_setup (int gpio, int direction)`
     196   - Setup des broches en INPUT ou OUTPUT
     197   - `gpio` : un numéro de broche légal
     198   - `direction` : 0 = INPUT, 1 = OUTPUT
     199   - Rend 0 si pas d'erreur; -1 en cas d'erreur.
     200
     201* `int gpio_read (int gpio, int * val)`
     202   - Lecture d'une broche
     203   - `gpio` : un numéro de broche légal
     204   - `* val` : pointeur vers un buffer qui contiendra la valeur lue
     205   - Rend 0 si pas d'erreur; -1 en cas d'erreur
     206
     207* `int gpio_write (int gpio, int val)` : écriture d'une broche
     208   - Ecriture d'une broche
     209   - `gpio` : un numéro de broche légal
     210   - `val` : valeur à écrire
     211   - Rend 0 si pas d'erreur; -1 en cas d'erreur
     212
     213= 3. Arduino
     214
     215== 3.1. Objectif
     216
     217L'objectif de vous familiariser avec l'environnement Arduino. Vous allez donc utiliser des cartes Arduino et y programmer une petite application.
     218
     219== 3.2. Environnement
     220
     221Il existe beaucoup d'excellents tutoriels sur l’Arduino, et il ne s'agit pas ici de remplacer par un tutoriel simplifié. Si l’Arduino vous intéresse au-delà de ce que nous allons brièvement aborder, vous pouvez commencer par l'excellent tutoriel d'[https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/ Eskimon].
     222
     223L'application Arduino est déjà installé sur les machine du département, pour la lancer, il suffit de taper son nom sur un terminal :
     224{{{
     225$ /opt/arduino.1.6.8/arduino &
     226}}}
     227La fenêtre d'édition apparaît. Elle va permettre d'éditer, de compiler et de téléverser (upload) votre programme dans le microcontrôleur ATmega. Vous allez devoir commencer par sélectionner la carte et le port de connexion (menu outils).
     228* carte : Arduino nano 328p
     229* port : /dev/ttyUSB0 ou /dev/ttyUSB1
     230Le port n'apparait que lorsque vous connectez la carte. l'hôte USB détecte et reconnaît la carte au moment de sa connexion et installe le driver (maintenant vous savez comment :-).
     231
     232== 3.3 Travail demandé ==
     233
     2341. faire clignoter une led 13 (exemple blink)
     2352. Lire le port analogique A0, sur lequel est branché une photorésistance et allumer la led 13 si la lumière détectée est sombre.
     236{{{
     237
     238  5V <----(/\LCR/\)--+--[/\/2kOhms/\/]----|0V
     239                     |
     240                     v
     241                     A0
     242}}}
     2433. Utiliser la photorésistance pour simuler un bouton poussoir, l'appui serait juste l'éclairage par un flash. A la détection de cet "appui", vous afficher un message sur le terminal.
     244
     245= 4. Compte rendu (CR)
     246
     247Vous écrirez un CR **au format markdown**, dans lequel vous mettrez les étapes de configurations de votre compte pour réaliser le TP, ainsi vous conserverez une trace.
     248Vous ajouterez vos codes commentés (succinctement mais proprement).
     249
     250Contraintes :
     251- Le fichier doit impérativement être nommé `peri_tp1_nom1_nom2.md`
     252- Vous enverez le CR par mail à franck.wajsburt@lip6.fr
     253avec le sujet: `[PERI] CR TP1 nom1 nom2`