Locale Alexa

Il s’agit d’implanter un agent conversationnel complètement autonome sur une Raspberry Pi 3 B+. Le but est de ne pas être dépendant du réseau.
L’article actuellement traite de la reconnaissance de la parole spontanée. Une première partie concerne l’installation de Python et des packages de deep learning. Dans une seconde partie, on teste la reconnaissance de parole, basé sur un système performant « Wav2Vec2 ».

Le but de cet article :

  • installer un environnement virtuel pour python
  • ajouter du swap (point technique)
  • installer les packages pytorch et transformers (Hugging Face/Meta)
  • utiliser la librairie transormers, pour :
  1. utiliser wav2vec2 pour la reconnaissance de la parole
  2. comparer les temps de calcul avec un PC sous linux

Mise en place de Python et des packages

Ci-dessous, de quoi faire une mise à jour du Rpi + installation du gestionnaire de version git (et d’autres trucs qui traînent là… à vous de creuser un peu, c’est p-e parfaitement inutile ou déjà installé)

sudo apt update
sudo apt upgrade
sudo apt install libffi-dev libbz2-dev liblzma-dev libsqlite3-dev libncurses5-dev libgdbm-dev zlib1g-dev libreadline-dev libssl-dev tk-dev build-essential libncursesw5-dev libc6-dev openssl git

En novembre 2022, plus besoin d’installer python 3.7 parce qu’il est présent d’office dans les versions récentes de l’OS, cependant il est plus prudent d’utiliser un environnement virtuel qui permet d’éviter de « tout casser ».

On va utiliser virtualenv, il y a bcp d’autres possibilités, j’ai l’habitude sous PC d’utiliser anaconda, mais là ça me paraît bcp plus light. L’installation est expliquée dans ce lien : https://raspberrypi-guide.github.io/programming/create-python-virtual-environment

Ci-dessous, la création d’un env virtuel « main » avec virtualenv (une fois virtualenv installé)

$ mkvirtualenv main
$ workon main
$ which python3
/home/pi/.virtualenvs/main/bin/python3
$ python3 --version
Python 3.7.3
$ pip install --upgrade pip

C’est tout bon! l’environnement virtuel (c-a-d séparé du reste du système, en partie) et python 3.7
(on sort de l’env avec la commande « deactivate »)

Avant de passer aux modèles de réseaux de neurones avec pytorch, on va devoir ajouter de la mémoire pour le swap

LE SWAP parce que le Rpi 3 n’a qu’1 Go de RAM (le Rpi 4 à 2 Go ça ne serait pas nécessaire. Bizarrement, on disant autrefois que si on a X Go de RAM il faut un swap deux fois plus grand, aujourd’hui sur Ubuntu et Debian (c’est les cas que je connais), ce n’est plus le cas par défaut on a quelques centaines de Méga. Parce que les ordinateurs modernes ont suffisamment de RAM j’imagine et parce qu’un swap de 16 ou 32 Go ça fait bizarre. Bref vous m’avez compris on a 1 Go de RAM et 100 Mo de swap, let’s add 512 Mo de swap: DEUX SUPERS ARTICLES EN FRANÇAIS : https://standartux.fr/astuces-ajout-de-swap-a-la-mano/ ET https://www.it-connect.fr/comment-ajouter-de-lespace-de-swap-sur-gnu-linux-debian-10/

créer le fichier de swap:
$ sudo dd if=/dev/zero of=/swap.file bs=1024 count=512000

$ sudo chmod 600 /swap.file
editer /etc/fstab comme indiqué dans le tutoriel,
$ sudo mkswap /swap.file
pour activer
sudo swapon /swap.file,

pour vérifierla mémoire utiliser la commande free -h :

total used free shared buff/cache
Mem 874Mi 123Mi ???? ???? ????
Swap 599Mi 10Mi 589Mi ???? ????

au moins si on dépasse les 800 Mo d’utilisation de la mémoire RAM, ça ne va pas complètement geler le Raspberry pi

On va installer pytorch, le paquet de d’apprentissage machine (profond ou pas) et de réseaux de neurones (profonds ou pas)

On récupère le build (wheel) sur un dépôt sur github : https://github.com/radimspetlik/pytorch_rpi_builds (au 10/2022)

Pytorch Raspberry Pi builds / Installing downloaded wheels

$ git clone https://github.com/radimspetlik/pytorch_rpi_builds.git
$ cd pytorch_rpi_builds,
$ cd torch
$ pip3 install torch-1.5.0a0+4ff3872-cp37-cp37m-linux_armv7l.whl
Idéalement il faudrait installer python 3.8 si on veut installer torchvision

Reconnaissance de la parole avec Wav2Vec2

On va faire de la reco de la parole offline (enregistrée) avec le package transformers fourni par meta/hugging face (https://huggingface.co/), https://huggingface.co/docs/transformers/model_doc/wav2vec2,
Wav2Vec2 est vraiment un bijou de technologie, il transforme un audio brut, pas des caractéristiques issues de l’audio, comme le spectrogramme mel, basé sur transformée de Fourier à court terme.

Wav2Vec2 réalise cette performance de prendre en entrée le signal brut, la forme d’onde, et de prédire non pas les phonèmes, mais les lettres! C’est un peu comme s’il avait appris à écrire (attention avec l’anthropomorphisme en IA, il faut vraiment s’en méfier).
La base du système est le module Wav2Vec, qui est appris sur une quantité astronomique de parole non transcrite, de manière dite non supervisée (pas de tâche précise), grâce à un critère appelé « contrastive predictive coding« . Après s’ajoute à cela une quantification vectorielle et l’utilisation de transformers, voir le papier fondateur « Attention is all you need ».

Codons un peu tout ça:

Pur l’intstallation de transformers sur CPU uniquement : pip install transformers[pytorch]

J’ai repris un code du site hugging face en le modifiant un peu. Sur le dépôt et le hub de hugging face, on trouve du code et des modèles etc. Hugging Face se met en position de leader dans le domaine des transformers et de la NLP (Natural Language Processing)
On utilise le modèle facebook/wav2vec2-base-960h, « base » signifiant qu’il est de taille raisonnable.
Mon code Python se trouve sur le dépôt https://github.com/laurentbenaroya/rpi_speech :
$ git clone https://github.com/laurentbenaroya/rpi_speech.git
$ cd rpi_speech
Le script est speech2text_wav2vec2.py

workon main
python3 -m pip install -r requirements.txt
python3 speech2text_wav2vec2.py ./audio/p232_228.wav

le téléchargement du modèle et du « processor » se fait lors du premier appel à la fonction, après il est stocké en cache.

Output de la commande ci-dessus :

facebook/wav2vec2-base-960h

tokenize
Elapsed time 0.32 sec

retrieve logits
Elapsed time 11.65 sec

take argmax and decode
Elapsed time 0.02 sec

transcription : LY EVIDENT THAT THE TIME FOR AN INQUIRY WILL COME

Ce n’est qu’un exemple mais la reconnaissance de la parole semble fonctionner. Il faudrait naturellement faire un benchmark. Le point important est que l’extrait ne dure que 2.63 secondes et est traité en 12 secondes. C’est très long dans la perspective d’un agent conversationnel. Par contre, niveau reconnaissance de la parole, c’est top.
Alors c’est tentant, on va faire la même chose sur mon PC (Intel® Core™ i5-6500 CPU @ 3.20GHz × 4 cœurs; 8 Go RAM; 64 bits; pas de GPU),
le temps total de calcul (tokenisation + inférence modèle + décodage) = 0.28 secondes, ce qui est parfaitement acceptable comme latence (je n’aime pas le terme « temps réel »), la véritable différence se situe sur l’appel au modèle (11.65 secondes sur Raspberry Pi 3 B+ contre 0.28 secondes sur PC en utilisant le CPU uniquement). Boum! Évidemment on comprends mieux pourquoi les agents conversationnels utilisent sur le cloud.

Affaire à suivre …

Transférer des fichiers entre un ordinateur sous Linux et un smartphone sous Android

Ayant fait l’acquisition d’un smartphone sous Android 8 il y a de ça quelques jours, l’une des premières choses que j’ai essayée de faire c’est d’uploader/téléverser de la musique sur mon appareil.

Il faut préciser que mon ordi tourne sous Linux Debian 10. J’ai un dual boot Windows avec licence, mais je l’utilise très peu, sauf pour les jeux.

J’ai donc utilisé mon moteur de recherche préféré (on se demande lequel quand on achète un android!) et cherché comment mettre de la musique sur le smartphone. Ayant eu un smartphone de la même marque il y a de ça une dizaine d’années, j’ai cru que j’allais brancher mon câble USB et voir apparaître le dossier où mettre ma musique! Bye bye iTune! O que non, ça n’est plus aussi simple!!!!

Je n’ai pas forcément essayé de comprendre le pourquoi du comment, mais j’ai trouvé une solution qui me convient. Certes, elle a l’inconvénient de demander des connaissances réelles en informatique et en particulier des commandes Unix. ça n’est pas un problème pour moi et j’espère pour vous aussi!!!

Bon, j’avais commencé par utiliser AirDroid, qui est possède une jolie interface web permettant de communiquer entre le smartphone et mon ordi via une interface web https://web.airdroid.com/

Grosse, grosse déception : impossible de téléverser/uploader des fichiers de plus de 30 Mo et une limitation du nombre total de Mo uploadés, vraiment basse. La solution c’est une version premium payante.

Alors je suis allé me promener, il faisait beau, je suis allé acheter des piles pour ma télécommande de télé. Bref, j’ai réfléchi et je me suis dit : NO WAY!

Comme indiqué là https://vxlabs.com/2014/11/06/use-adb-to-bypass-dog-slow-mtp-transfer-of-files-from-android-to-linux/ il existe une alternative pour qui connaît un peu les commandes shell sous Linux. L’interface s’appelle ADB (Android Debug Bridge) https://developer.android.com/studio/command-line/adb

Cela suppose donc des connaissances des lignes de commande et a priori de travailler sous Linux! En fait tout ce dont on a besoin est le Android SDK Platform-Tools package https://developer.android.com/studio/releases/platform-tools … qui est disponible sous Linux, Windows et Mac.

Il semblerait donc que ce soit jouable sous Windows aussi (Mac est orienté Unix, donc rien d’étonnant là). Il restera à apprendre quelques lignes de commandes, qui sont accessibles à un utilisateur de niveau « moyen-supérieur ». Si vous voulez un truc avec une interface graphique et tout, passez votre chemin…

Je ferai peut-être un post sur la mise en place et l’utilisation de ADB sous Windows, vu que j’ai le dual boot.

Bon ADB : bien je suis trop content : ça marche! Je vais détailler la marche à suivre

Tout d’abord, vous trouverez tout ce dont vous avez besoin dans les pages suivantes https://developer.android.com/studio/command-line/adb, https://developer.android.com/studio/releases/platform-tools

Pour commencer, vous devez télécharger le Android SDK Platform-Tools, il suffit de cliquer sur le lien dans la page https://developer.android.com/studio/releases/platform-tools « Download SDK Platform-Tools for Linux » (si vous êtes sous Linux naturellement). Enregistrer le fichier, créer un répertoire, dé-zippez le ensuite dans un terminal (gnome-terminal pour moi):

cd
mv ~/Downloads/platform-tools_r30.0.5-linux.zip .
unzip platform-tools_r30.0.5-linux.zip
cd platform-tools/

Dans le répertoire platform-tools, vous avez un certain nombre d’exécutables dont adb, qui est celui qui nous intéresse ici.

Alors vous pouvez télécharger le SDK complet https://developer.android.com/studio/intro/update#sdk-manager, si vous avez en tête de faire du dev pour Android, mais je ne l’ai pas fait parce que ça bouffe des Go et surtout dans le but d’y aller doucement.

Tout d’abord, il faut activer le mode développeur sur votre smartphone. Ce qui est indiqué, c’est :

On Android 4.2 and higher, the Developer options screen is hidden by default. To make it visible, go to Settings > About phone and tap Build number seven times.

Sur Android 4.2 et supérieur, l’écran des options du développeur est caché par défaut. Pour le rendre visible, allez dans Paramètres > À propos du téléphone et appuyez sept fois sur Numéro de build.

Perso, comme je n’avais pas traduit le texte, j’ai cru qu’il fallait taper sept fois le « numéro de build » qui faisait déjà une vingtaine de caractères, argh! Et où? That was the question!

Bon, je suis allé dans Paramètres > A propos du téléphone > Informations sur le Logiciel. Là j’ai « tapé » sept fois sur « Numéro de version » et j’ai rentré mon mot de passe (celui pour déverrouiller le téléphone). Et miracle, ça marche! Dans « Paramètres » apparaît un onglet « Options de développement ». Je clique dessus, je l’active si besoin et j’active « Débogage USB » si ce n’est pas déjà le cas.

Bon je suis très fort, mais c’est avec mon moteur de recherche préféré, toujours lui, que j’ai trouvé la solution détaillée ici : https://www.samsung.com/uk/support/mobile-devices/how-do-i-turn-on-the-developer-options-menu-on-my-samsung-galaxy-device/ en Anglais, mais avec de belles illustrations.

OK, maintenant vous savez que j’ai un Samsung Galaxy (d’occaz). Il doit y avoir moyen trouver la procédure équivalente pour activer les options de développement sur n’importe quel smartphone sous Android.

Ensuite, j’ai connecté mon Samsung à mon ordi via un cable USB. J’ai dû accepter un certain nombre de trucs, peut-être retaper mon mot de passe (je ne sais plus exactement) :

When you connect a device running Android 4.2.2 or higher, the system shows a dialog asking whether to accept an RSA key that allows debugging through this computer. This security mechanism protects user devices because it ensures that USB debugging and other adb commands cannot be executed unless you’re able to unlock the device and acknowledge the dialog.

Lorsque vous connectez un appareil fonctionnant sous Android 4.2.2 ou supérieur, le système affiche une boîte de dialogue vous demandant si vous acceptez une clé RSA qui permet le débogage via cet ordinateur. Ce mécanisme de sécurité protège les appareils des utilisateurs car il garantit que le débogage USB et les autres commandes adb ne peuvent être exécutés que si vous êtes en mesure de déverrouiller l’appareil et d’accuser réception de la boîte de dialogue.

Pour info, une clef RSA est une clef pour système de cryptage asymétrique qui permet à un ordi de se connecter à un autre ordi en toute sécurité. Il y a une clef publique et une clef privée. Je l’utilise pour me connecter en « ssh » sur des serveurs sans avoir à taper à chaque fois mon mot de passe. Pour plus d’information, vous pouvez chercher « chiffrement RSA » sur votre moteur de recherche … préféré.

Bon maintenant, on va connecter le smartphone à votre ordinateur via la Wifi (cool!)

Là je reprends presque exactement ce qui est indiqué dans https://developer.android.com/studio/command-line/adb, à la section « Connect to a device over Wi-Fi (Android 10 and lower) », comme indiqué, pour un Android 10 ou inférieur. J’ai un smartphone sous Android 8, donc c’est bien pour moi. Sinon il faut se référer à la section « Connect to a device over Wi-Fi (Android 11+) », que je n’ai pas lue pour être honnête.

1. Le cable usb branché, je tape

./adb tcpip 5555

puis je peux déconnecter mon cable USB

2. Il faut trouver l’adresse ip de votre smartphone, qui commence par 192.168 (adresse sur le réseau local). Comme indiqué dans le document su-cité, Paramètres > Connexions > Wi-Fi, puis sélectionner « Réseau Actuel » et l’adresse ip locale apparaît, 192.168.1.24 pour moi par exemple. (puis taper sur « annuler » pour revenir en arrière).

./adb connect 192.168.xxx.xxx (remplacer par votre adresse ip naturellement)
./adb device

List of devices attached
192.168.xxx.xxx:5555 device

3. Ensuite, on peut commencer à jouer!

# pour voir ce qu'il y a sur la carte SD
./adb shell ls /sdcard
# pour voir ce qu'il y a dans le répertoire Music du la carte SD
./adb shell ls /sdcard/Music
# pour initier un shell
./adb shell
$ ls
$ ls sdcard
$ ls storage/0E64-F84B/DCIM/Camera/  # le nom du répertoire dans storage "0E64-F84B" est certainement différent chez vous, "DCIM" contient les photos
$ exit

Pour copier les photos depuis le smartphone dans le répertoire /home/benaroya/Images/samsung/Camera (remplacer benaroya par votre nom d’utilisateur!!!), on utilise la commande pull

./adb pull storage/0E64-F84B/DCIM/Camera/ /home/benaroya/Images/samsung

Pour copier un fichier audio depuis votre ordinateur vers le smartphone, utiliser la commande push

./adb push Brooke_Annibale_song_1.mp3 /sdcard/Music

Si vous aimez la Pop/Folk, je vous conseille Brooke Annibale, c’est de la balle. Je l’ai découverte sur Audiotree Live que je vous recommande aussi.

Enfin, pour fermer la connexion (important)

./adb devices -l
./adb -s mydevice disconnect

remplacer mydevice par le code qui apparaît après « device: »
sinon pour déconnecter tous les appareils d’un coup, taper ./adb disconnect tout simplement.

Nous avons vu comment télécharger vos photos sur votre ordi local et comment téléverser votre musique sur votre smartphone via la Wi-Fi. Il ne reste plus qu’à jouer la musique, avec Poweramp par exemple (il faut re-scanner toute la musique dans ce cas).

Le seul défaut de la procédure, c’est qu’il faut brancher le smartphone à votre ordinateur via un câble USB pour initier la connexion TCP. Mais je trouve ça super chouette de téléverser de la musique via la WiFi de cette manière.

Et voilà!!!

Remarque a posteriori : on peut aisément mettre le répertoire contenant l’exécutable « adb » dans le PATH, de manière à ne pas avoir à se placer dans le répertoire en question puis taper ./adb à chaque manip.

Sloeber, une alternative à l’IDE Arduino

Il est de notoriété publique que l’IDE mis à disposition par Arduino est limité. Autant ça peut être pratique avec seulement deux fonctions à éditer (setup et loop), ce qui le rend simple. La chaîne de traitement de la compilation du code au téléversement est entièrement transparente.

Du point de vue de l’éditeur textuel, c’est vraiment nul à mon avis. Quand on fait du Python avec Pycharm (ou Spyder j’imagine), on se dit mais c’est quoi cet éditeur, pas de complétion, pas d’analyse syntaxique et j’en passe.

Il y a des alternatives. Je me suis tourné (hier dans la nuit) vers un IDE basé sur Eclipse, éditeur professionnel, généraliste et libre. Pour intégrer les fonctionnalités Arduino, Il est conseillé de télécharger le bundle Sloeber plutôt qu’Eclipse puis le plugin Arduino. A noter et c’est important, Eclipse est disponible sous Linux, Windows et Mac OS X.

Alors oui Eclipse, c’est un truc qui doit peser 1 Go. Mais bon il faut arrêter de se mentir, c’est pas trop gênant avec la taille des disques durs actuels (sauf si on a un Macbook avec 128 Go en SSD – je le sais, j’en ai un).

Bref, j’ai téléchargé puis installé le bundle – pour Linux (pas pour Mac OS X, je n’ai plus de place 🙂 ). Sur le site de Sloeber, c’est facile, tout est expliqué, il faut juste s’habituer à la façon dont les choses sont présentées. Vous me direz, alors pourquoi cet article?

Et bien pour deux raisons:

  1. ça a le mérite de mettre en avant un IDE alternatif et crédible pour Arduino et autres micro-contrôleurs.
  2.  j’ai galéré sur un point que je vais expliciter ci-dessous et qui pourra être utile à d’autres personnes.

J’ai donc téléchargé le bundle et j’ai créé un premier projet. Et là blocage, pas moyen de trouver mon cher Arduino Uno. Je suis devant une fenêtre :

Arduino_info

Et pas moyen de changer le « Platform folder », je ne trouve pas l’Arduino Uno dans Board.

La solution : aller dans l’onglet (en haut) Arduino -> préférences, puis « Platforms and boards »

platforms_boards2Puis arduino -> Arduino AVR Boards -> la dernière version:

J’avoue, c’est tout simple, mais je n’ai trouvé aucune mention sur ce problème sur le net, que ce soit en français ou en anglais.

Après vous pouvez démarrer un projet comme d’habitude

sloeder_arduino_pin13

Il y a beaucoup plus de possibilités qu’avec l’IDE Arduino naturellement. Déjà à droite, nous avons les variables et fonctions du fichier. Dans la fenêtre du milieu, on peut compléter les noms (complétion). Les erreurs de syntaxe sont soulignées en rouge. On peut « refactorer ». Enfin il y a une myriade  de possibilités. Truc intéressant, si on passe la souris sur une fonction, on voit sa description et on peut ouvrir le fichier contenant sa déclaration. Enfin, il y a tout d’un vrai éditeur.

Je pense qu’un gros point fort de cet IDE par rapport au standard Arduino, c’est la possibilité de créer des librairies, de manière sereine. Je ne l’ai pas encore fait, mais ça me paraît logique. Impossible de le faire avec le seul IDE Arduino.

En conclusion, je vais continuer à explorer les possibilités de l’environnement Eclipse adapté à l’univers Arduino. Peut-être est-ce un leurre. Mais je pense que ça peut valoir le coup, si on veut aller un peu au-delà du programme avec la fameuse led 13 qui clignote!

Retour d’expérience

J’ai utilisé Eclipse/Sloeber pendant quelques jours et je suis revenu à l’IDE Arduino. Je m’explique. Sloeber est très pratique pour naviguer dans les librairies (simple clic droit sur une variable ou une fonction liée à la librairie). Mais, sous Linux, cela est tout à fait faisable en ligne de commande avec find et grep, puis avec une édition avec (vs) code par exemple.

Là où j’ai eu un gros souci avec Sleober, c’est quand j’ai voulu utiliser une ESP8266, alors que j’avais débuté avec un  Arduino Uno. La gestion des bibliothèques devient pénible. Je n’ai pas souhaité aller plus loin parce que l’IDE est censé me faire gagner du temps, pas en perdre en me prenant la tête. Bref une expérience mitigée. J’ai lu quelque part sur un forum qu’il est faut avoir une bonne raison pour passer à Eclipse/Sloeber. Cependant, je vous conseille d’essayer juste pour « sentir » les limitations de l’IDE Arduino.

Et voilà!

Résolution d’un problème numérique sur un composant fortement non-linéaire dans LTspice

Comme dans le post précédent, nous utilisons un « Voltage Controlled Switch » pour charger un condensateur, puis ouvrir le circuit. Nous allons prendre cet exemple pour illustrer un problème de simulation avec un composant fortement non linéaire.

Voici le circuit:

Le schéma LTspice est disponible ici

Nous avons volontairement choisi des valeurs de Ron très petite et Roff très grande.

Ci-dessous, avant t=1s, le circuit est fermé (Ron=0.0001 Ω), car la tension du sw (en rouge) est supérieure à 1V. La capa est chargée. A t=1s exactement, la résistance du switch passe brutalement de Ron=0.0001 Ω à Roff = 1M Ω. Le rapport Roff/Ron est très grand (1e+10).

La tension aux bornes du condensateur (en vert) chute lorsque que le commutateur passe de Ron à Roff, ce qui n’est pas logique.

C’est un problème de simulation. Le comportement du switch est instantané donc fortement non linéaire (voir tolerance on errors, en Anglais).

Si une large gamme de résistance ON à OFF doit être utilisée dans les interrupteurs (ROFF/RON >1e;+12), alors la tolérance sur les erreurs permises pendant l’analyse des transitoires doit être réduite en utilisant la ligne de contrôle .OPTIONS et en spécifiant que TRTOL est inférieur à la valeur par défaut de 7.0. Lorsque des interrupteurs sont placés autour des condensateurs, l’option CHGTOL doit également être réduite. Les valeurs suggérées pour ces deux options sont respectivement 1.0 et 1e-16. Ces changements incitent SPICE3 à être plus prudent autour des points de commutation afin qu’aucune erreur ne soit commise en raison de la modification rapide du circuit.

La solution consiste à ajouter la directive « .options trtol=0.001 » dans le schéma LTspice :

On peut aussi changer dans le « control Panel » -> « Spice », la valeur de TrTol de 1 à 0.001. C’est une solution « moins propre ».

Nous lançons la simulation :

Miracle, les choses s’arrangent!

En fait, je n’ai pas une compréhension réelle des paramètres de simulation. Je suis arrivé à cette solution grâce à la page web sus-citée et en cherchant « la bonne valeur » de Trtol (et ChgTol) en tâtonnant.

Et voilà!

Charge et décharge d’un condensateur avec un « Voltage Controlled Switch »

Mes deux posts sur LTspice ont eu du succès. J’ai décidé d’en faire un troisième, assez long. J’en profite pour faire de la pub sur d’autres articles de mon blog concernant des sujets tout aussi passionnants comme TensorFlow ou encore la BeagleBone Black (qui est vachement moins connue, je l’admets, mais c’est de la balle!). Surtout, n’hésitez pas à laisser des commentaires !!!

Problématique

Voilà le problème, qui m’a été soumis par mon beau-père, il y a déjà fort fort longtemps, du temps où j’étais jeune quoi.
Chargeons un condensateur dans un premier temps par une alimentation continue. Dans un second temps nous « débranchons » la source de tension et nous mettons un second condensateur, vide, en parallèle. Pas d’autre composant. Quelle sera alors la tension aux bornes des deux condensateurs?

Mon intuition me dit que la tension sera divisée par 2 puisque la charge sera répartie entre les deux capas. Si on note U la tension initiale du premier condensateur chargé et Uf la tension finale en régime stationnaire. Est-ce qu’on a Uf = U/2?

D’un autre côté, l’énergie stockée dans un condensateur est de 1/2 C U*U (voir ici pour le calcul de l’énergie). Si on note C1 la valeur du condensateur qu’on charge au début et C2 celui qui est déchargé. L’énergie avant de fermer le circuit est de :
Après, en « régime stationnaire », l’énergie sera répartie sur les deux capas :
où Uf est la tension finale que nous voulons calculer. Comme il n’y a pas de résistance dans le circuit, l’énergie est conservée :
Si les capas sont égales C1  = C2 = C, on  obtient On en déduit que la tension finale sera égale à la tension initiale divisée par la racine carrée de 2. Et cela quelque soit la capacité (égale) des condensateurs. Étonnant non?

Voyons ça dans LTspice.
Dans une première partie, nous allons nous familiariser avec le composant « Voltage Controlled Switch » qui permet de simuler un interrupteur.
Dans la seconde partie, nous étudierons le problème posé – en utilisant 2 composants « Voltage Controlled Switch ».

Partie I : « Voltage Controlled Switch » dans un circuit RC

Pour simuler ce truc, nous allons avoir besoin d’interrupteurs, un pour ouvrir le circuit de charge et un second pour fermer le circuit capacitif.

Or, il n’existe pas d’interrupteur simple dans LTspice et cela paraît logique parce c’est de la simulation, l’interrupteur est soit dans une position, soit dans une autre, mais une unique position par simulation. Pour commuter automatiquement, il faut adopter une autre stratégie.
Nous allons utiliser un composant appelé « Voltage Controlled Switch ». Voir discussion créer un interrupteur LTpsice.

Dans un premier temps, nous allons étudier un circuit RC simple et y ajouter un composant sw « Voltage Controlled Switch ». Ce composant sw a une résistance qui peut « switcher » entre deux valeurs en fonction d’une tension et d’un seuil. En fixant la résistance à une valeur faible (< 1 Ω) dans un cas et à une valeur grande dans l’autre cas (> 1 M Ω, voire plus), cela permet de simuler un interrupteur, contrôlé par une tension externe. En fait, il va y avoir un circuit principal (RC dans ce cas) et un second circuit avec une unique source de tension (composant « voltage »). Celui-ci pilote l’interrupteur (switch) .

Noter qu’il existe le même type de composant contrôlé en courant « Current Controlled Switch » csw, mais nous n’en parlerons pas dans ce post.

Le composant sw « Voltage Controlled Switch »

Dans un circuit RC, on introduit le composant sw:

En faisant un clic droit sur le composant sw, j’ai mis la valeur « value » à « monSW ». Il nous faut ajouter trois choses :

  1. une source de tension pour piloter pour le sw
  2. une directive pour spécifier les résistances du composant sw et la tension seuil
  3. le temps d’étude en régime transitoire (run, transient)

On ajoute une « spice directive », qu’on trouve soit sur la barre d’outil, soit dans l’onglet « édition » -> « Spice directive ». On ajoute la directive .model monSW SW(Ron=1 Roff=1Meg Vt=1 Vh=0). Cela signifie que le composant que j’ai renommé monSW à une tension seuil Vt de 1V – une tension d’hystérésis Vh de 0V, c-a-d que le seuil de déclenchement est le même en diminuant ou en augmentant la tension de commande – une résistance Ron de 1 Ω si la tension externe est supérieure à Vt et une résistance de 1 M Ω  si la tension est inférieure à Vt . Du coup, si la tension est supérieure à 1 V, le circuit est fermé et sinon le circuit est considéré comme ouvert. On peut ajuster Ron et Roff si bessoin Voir ici pour plus d’information (en Anglais).

Ensuite, on règle la tension de commande. Click droit sur le composant voltage entouré en rouge dans la figure ci-dessus et puis on clique sur « advanced »

 

On choisit/coche PWL(t1 v1 t2 v2) à gauche et pour t=0 on met 2V et pour t=2 (secondes) on met 0V.  La tension va passer linéairement de 2V à 0V en 2 secondes.

Du coup, la résistance au départ est de 1 Ω et la tension va passer en dessous de 1V à t= 1 seconde et ouvrir le circuit (1 M Ω).

Reste à cliquer sur le petit bonhomme qui court dans la barre à outils, ou aller dans l’onglet « simulate » puis « run ». Une fenêtre s’ouvre et on met 3 secondes pour le « Stop time »  et on coche la case « Start external DC supply voltages at 0V » ça nous donne la directive suivante: « .tran 3 startup ».

Au final, le circuit est:

On trace les courbes. En bleu, la tension « de commande ». En vert, la tension aux bornes du condensateur.

La courbe en bleu passe en dessous de 1V au temps t= 1 seconde. Donc avant 1 s, le circuit est fermé et la tension aux bornes de la capa est de 5V. Quand le circuit est ouvert, à partir de 1 seconde, le condensateur se décharge dans la résistance.
Du fait que le produit RC=0.1, la tension est divisée par 10 en 0.23 secondes. Et donc, la tension aux bornes de la capa est de 0.5 V à t=1.23 s.

Le fichier LTspice du circuit est disponible ici.

Partie II : charge d’un condensateur et circuit purement capacitif

Les étapes de construction du circuit sont moins détaillées que dans la première partie.

On met d'abord en place un circuit purement capacitif avec un switch en série..
On met en place le premier interrupteur de manière similaire à la partie I, avec une source de tension pour le piloter.
Même réglage de la tension qui pilote interrupteur que dans la partie I : l'interrupteur s'ouvre à t=1 sec.
Figure ci-dessous: ajout d'une seconde capa et d'un second interrupteur pour connecter les deux condensateurs ensemble à t=3 secondes.
Réglage de la tension qui pilote le second interrupteur: 0V pendant 2 sec puis 2V à 4 sec, linéaire. Ainsi le seuil 1V est dépassé à 3 sec, l'interrupteur numéro 2 se ferme.

Une fois les deux générateurs de tension qui pilotent les interrupteurs réglés:

Finalisation du circuit: les directives spice pour les « Voltage Controlled Switches ».
On a utilisé le même modèle pour les deux interrupteurs (monSW1 et monSW2). Les directives « .model monSW1 SW(…) » et « .model monSW2 SW(…) » sont identiques: une résistance Ron à 1 Ω et Roff à 100 M Ω et une tension seuil de 1 Volt.

Circuit final:

Le fichier LTspice du circuit est disponible ici.

Le hic!!!

Ci-dessous les courbes: en vert la tension aux bornes de C1 et en bleu la tension aux bornes de C2. En marron, la ligne constante à 1V. Au départ, Le condensateur 1 est très rapidement chargé. Le premier interrupteur s’ouvre à t=1s et le second interrupteur se ferme à t=3s.

Le premier switch s’ouvre à t=1 seconde, car la courbe bleu claire passe en dessous de 1V et le second switch se ferme à t=3 secondes, car la courbe rouge passe au-dessus de 1V.

La tension aux bornes des 2 capas est : 2.5 Volts, soit U/2 et non pas U/racine(2).

Explication possible

La charge électrique q d’un condenseur s’écrit : q = C U.
Lorsqu’on met les deux condensateurs en parallèle, la charge électrique reste la même, mais la capacité C est multiplié par deux. Par conséquent, la tension est divisée par deux: q = C U = 2C U/2.

Vraiment bizarre!!!!

Liens utiles:
tutoriel pour apprendre à utiliser LTspice
Les raccourcis clavier
changer la taille des lignes et des caractères sur les figures (en Anglais)
cours sur les condensateurs
créer un interrupteur sous LTspice (discussion)

Les entrées analogiques de la Beaglebone Black, ARM et PRUs

L’objectif ici est de compiler et d’exécuter un programme permettant de lire une tension sur des pins analogiques. Deux programmes, en fait, l’un côté PRU (Programmable Real-time Unit) et l’autre côte CPU ARM. Finalement, j’ai opté pour les exemples fournis par Texas Instruments, qui est le constructeur du « cœur » (SoC AM3358/9) de la BBB. Au départ, je ne saisissais pas bien comment lancer les programmes fournis par TI, ni l’intérêt exact du SDK. J’ai en plus installé leur « Code Composer Studio » sur ma bécane (CCS), qui prend moultes Giga et est bien complexe. Je vais probablement le désinstaller.
Grâce au projet BeagleScope, dont je parle dans mon précédant post,  en étudiant le fichier deplay.sh, j’ai compris comment lancer un programme (dans le firmware) sur l’un des deux micro-contrôleurs (les fameux PRUs).

Le premier exemple, dans le post précédent, consistait à faire clignoter une LED à partir d’un pin numérique configuré en « output ». Maintenant, nous allons construire et exécuter un projet, nommé « PRU_ADC_onChip » qui  a pour objectif de lire des valeurs sur des pins analogiques (ADC = Analog to Digital Converter) et de les convertir en Volts en fonction d’une tension de référence. Les ADC de la BBB ont 12 bits de résolution et prennent donc des valeurs entre 0 et 4096-1 (4096 = 2 puissance 12). La tension de référence pour les convertisseurs est de 1.8 V, au lieu des 3.3 V pour pour les pins numériques. ATTENTION, ne pas mettre une tension supérieure à 1.8 V au risque d’endommager laBeagleBone! La tension de référence est fournie sur le pin P9_32 (VDD_ADC) et une terre analogique sur le pin P9_34 (GROUNDA_ADC). Vraiment, faite attention de ne pas mettre une tension supérieure à 1.8 V dans les entrées analogiques, please!!!
Les pins d’entrée analogique, sur le header P9, sont numérotées de AIN0 à AIN6 (7 entrées), pins 33 et 35 à 40, le pin 34 étant la terre et le pin 32 étant la référence à 1.8 V.  Les entrées analogiques sont surlignées en vert dans la figure ci-dessous:

Une vidéo illustrant le « projet », dans ses grandes lignes, est disponible ici : How to Use the PRU to Control a Peripheral: PRU_ADC_onChip on Sitara 335x using Beaglebone Black. C’est une bonne idée de la regarder cette vidéo, elle ne dure que 10 minutes (si l’Anglais ne vous rebute pas).

Les explications dans ce post sont certainement transposables à d’autres BeagleBones (Green, Blue), moyennant quelques adaptations.
Note: la résolution est ici de 12 bits, contre 10 bits pour l’Arduino Uno. La résolution standard d’un fichier audio est de 16 bits (signé).
Du coup, cela signifie que le pas de quantification est de 1.8 V divisé par (2 puissance 12, moins 1), soit 0.440 mV environ!

Résumé avec la vidéo TI (traduction) :

Dans certaines situations, il est plus logique de contrôler un périphérique avec un processeur déterministe dédié plutôt qu’avec un cœur ARM à usage général dans un processeur TI. Les applications vont d’un système de surveillance dédié où la charge de traitement peut être déchargée de l’ARM à un environnement en temps réel où le stimulus nécessite une réponse du processeur dans un laps de temps connu. Cette vidéo fournit un exemple d’utilisation du noyau d’unité programmable en temps réel (PRU) pour contrôler un périphérique sur n’importe quel processeur TI avec un PRU-ICSS ou PRU_ICSSG. Dans ce cas, pour contrôler le convertisseur analogique-numérique (ADC) sur le processeur Sitara AM335x à l’aide du BeagleBone Black.

Sur le projet PRU_ADC_onChip :

Il s’agit d’un projet de référence pour l’utilisation du PRU-ICSS pour contrôler un périphérique ADC sur l’AM335x. Le but de ce projet est de fournir un modèle pour contrôler un périphérique sur puce à l’aide du PRU. Il démontre également une application de RPMsg pour la communication ARM-PRU.

Nous allons passer aux choses sérieuses, à savoir la compilation des deux codes, l’un sur la BBB pour le PRU et l’autre sur votre PC sous Linux pour le processeur ARM de la BBB.

La première étape consiste à modifier le fichier /boot/uEnv.txt, puis rebooter.
Dans ce fichier de configuration, il faut dé-commenter la ligne suivante :
disable_uboot_overlay_adc=1, afin d’empêcher le processeur ARM d’accéder à la conversion analogique numérique ADC, car ce sera la tâche du micro-contrôleur.
Re-booter :
sudo reboot now

La seconde étape: le projet fait partie du pru-software-support-package fourni par Texas Instruments (TI) et téléchargeable ici pru-software-support-package. Il est souhaitable de le télécharger sur votre PC, puis de le copier sur votre BBB :
scp pru-software-support-package-5.6.0.zip debian@beaglebone.home:/home/debian/
Sur les deux ordinateurs (PC et BBB), le décompresser :
unzip pru-software-support-package-5.6.0.zip
Le projet s’appelle PRU_ADC_onChip et se trouve dans le répertoire :  pru-software-support-package-5.6.0/examples/am335x/PRU_ADC_onChip.

La troisième étape (1/2) : installation du SDK sur le PC pour la compilation croisée.
On trouve le SDK de TI depuis PROCESSOR-SDK-AM335X, c’est un très gros fichier  « ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin » (9.2 Go après installation, sur mon PC) . Une fois téléchargé, il faut l’exécuter pour installer le SDK :
chmod u+x ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin
./ti-processor-sdk-linux-am335x-evm-06.03.00.106-Linux-x86-Install.bin


La troisième étape (2/2) : la compilation croisée (cross-compilation)
Il s’agit de compiler le programme depuis le PC (processeur x86) pour le processeur ARM de la BeagleBone, sur lequel il sera exécuté.
Le code source est dans le fichier pru_adc_userspace.c, qui se trouve dans le sous répertoire PRU_ADC_onChip/pru_adc_userspace
Attention, celui-ci doit être compilé sur votre PC.
Ce n’est pas indiqué explicitement dans le README.txt, mais c’est nécessaire.
Faire l’export suivant pour le dossier bin du SDK :
export ARM_CCT=/home/benaroya/ti-processor-sdk-linux-am335x-evm-06.01.00.08/linux-devkit/sysroots/x86_64-arago-linux/usr/bin
en remplaçant « /home/benaroya » par votre répertoire racine contenant le SDK
Dans le répertoire PRU_ADC_onChip/pru_adc_userspace, on compile :
make clean
make

Enfin, il ne reste plus qu’à recopier le dossier généré « gen » vers l’exemple sur la BeagleBone
scp -r gen debian@beaglebone.home:/home/debian/pru-software-support-package-5.6.0/examples/am335x/PRU_ADC_onChip/pru_adc_userspace/

La quatrième étape : compilation pour le PRU 0 sur la BBB.
dans PRU_ADC_onChip, compiler pru_adc_firmware.c dans la beaglebone :
export PRU_CGT=/usr/share/ti/cgt-pru
make clean
make

Vous pouvez insérer l’export dans ~/.bashrc, pour ne plus le faire à chaque connexion à la BBB.

La cinquième étape : démarrer le PRU.
Comme indiqué dans le post précédent, il faut mettre le code pour le PRU 0 dans le firmware et lancer le remoteproc0. Il y a une erreur dans le programme fourni par TI parce que  pru_adc_userspace.c essayez de lancer automatiquement PRU 1, alors que le programme « pru_adc_firmware.c » est compilé avec des options pour le PRU 0. ça n’a pas fonctionné en l’état chez moi.

Dans pru_adc_firmware.c :
/*
* The PRU-ICSS system events used for RPMsg are defined in the Linux devicetree
* PRU0 uses system event 16 (To ARM) and 17 (From ARM)
* PRU1 uses system event 18 (To ARM) and 19 (From ARM)
*/
#define TO_ARM_HOST 16
#define FROM_ARM_HOST 17

Dans pru_adc_userspace.c :
char firmware[] = "/sys/class/remoteproc/remoteproc1/firmware";
char pruState[] = "/sys/class/remoteproc/remoteproc1/state";

Remplacer remoteproc1 par remoteproc0 ne suffit pas bizarrement.

On revient à nos moutons: renommer et copier le code compilé dans le firmware,
cp PRU_ADC_onChip.out PRU_ADC_onChip-fw
sudo cp PRU_ADC_onChip-fw /lib/firmware/

et démarrer le programme sur le PRU 0
echo 'stop' > /sys/class/remoteproc/remoteproc0/state 2>/dev/null
echo "PRU_ADC_onChip-fw" > /sys/class/remoteproc/remoteproc0/firmware
echo 'start' > /sys/class/remoteproc/remoteproc0/state

Dernière étape : tester
./gen/pru_adc_userspace -c 5
Reading voltage at ADC Channel: 5
Voltage on ADC Channel 5 is 1.7960V
./gen/pru_adc_userspace -c 6
Reading voltage at ADC Channel: 6
Voltage on ADC Channel 6 is 0.9270V
./gen/pru_adc_userspace -c 7
Reading voltage at ADC Channel: 7
Voltage on ADC Channel 7 is 0.0501V

C’est magnifique, car physiquement, le pin AIN4 (canal 5) est rélié à l’analog VDD (1.8 V), le pin AIN5 (canal 6) est « au milieu » (pont résistif de 2k Ohms) et le pin AIN6 (canal 7) est à la masse. Cependant, c’est un peu fluctuant au cours du temps. Apparemment, il y a moyen de moyenner la mesure:
/*
* set the ADC_TSC STEPCONFIG1 register for channel 5
* Mode = 0; SW enabled, one-shot
* Averaging = 0x3; 8 sample average
* SEL_INP_SWC_3_0 = 0x4 = Channel 5
* SEL_INM_SWC_3_0 = 1xxx = VREFN (reduces noise in single ended mode)
* use FIFO0
*/
ADC_TSC.STEPCONFIG1_bit.MODE = 0;
ADC_TSC.STEPCONFIG1_bit.AVERAGING = 3;
ADC_TSC.STEPCONFIG1_bit.SEL_INP_SWC_3_0 = 4;
ADC_TSC.STEPCONFIG1_bit.SEL_INM_SWC_3_0 = 8;
ADC_TSC.STEPCONFIG1_bit.FIFO_SELECT = 0;

Discussion générale :
Nous avons compilé et testé ce projet pour la lecture d’une entrée analogique. Il est composé de deux codes, l’un pour le PRU 0 qui va lire une valeur sur un pin analogique. Cette partie du code est assez lisible. Ensuite, cette valeur (échantillonnée sur 12 bits) est envoyée au micro-processeur ARM. La communication entre PRU et ARM est assurée par le framework RPMsg (Remote Processor Messaging, voir peut-être ici). Ne connaissant pas ce framework, je vais me rencarder sur ce Graal.
Enfin, le second code, compilé sur mon PC , est exécuté sur la BBB par l’ARM. Celui-ci envoie une requête avec le numéro du canal et reçoit en retour la valeur mesurée. Enfin, celle-ci est convertie en Volts et affichée.

Conclusion :
Nous avons abordé, entre autres, le téléchargement du « pru-software-support-package » de Texas Instruments, l’installation du SDK sur le PC, la compilation des deux codes, l’activation du PRU et enfin nous avons fourni de bons résultats de l’exécution du programme sur ARM.
A noter que le PRU lit une seule valeur sur l’ADC  (one-shot). Il serait intéressant de lire des valeurs à intervalles réguliers et de les renvoyer à l’ARM. Aussi comprendre la communication entre PRU et ARM avec le RPMsg.

Et Voilà !!!

Programmer les « Programmable Real-time Units » de la BeagleBone Black (PRUs)

Dans ce post, on va apprendre à faire clignoter une LED avec le microcontrôleur PRU 0 (il y en a deux). L’objectif est d’apprendre à lancer un programme en C dans le micro-contrôleur. Après on peut modifier le programme pour faire un tas d’autres choses. C’est une base.
PRU signifie « Programmable Real-time Unit ».

J’ai perso eu du mal à démarrer avec les PRUs dans ma BeagleBone Black . Beaucoup de documents sur le net. Mais beaucoup utilisent les « tree obverlays » et les slots qui eux n’existent plus dans les versions récentes de la BBB. J’ai fini par faire clignoter ma LED après trois soirées de boulot. C’est frustrant, mais maintenant j’ai à peu près compris la logique. C’est ce que j’expose ici, en espèrant que ça vous sera utile!

Mon approche est basée sur Remoteproc, qui signifie « remote processor », c-a-d processeur distant. C’est une approche, récente, pour programmer les PRUs. Il y en a trois: remoteproc0, remoteproc1, remoteproc2. Comme on le voit ci-dessous, remoteproc2 est occupé. Les deux autres sont utilisables et correspondent aux PRU 0 et 1.

Pour bien commencer, lancer une connexion ssh dans un terminal
ssh debian@beaglebone.home

Dans le log au démarrage:
dmesg | tail -100
[ 11.957862] remoteproc remoteproc0: 4a334000.pru is available
[ 11.958057] pru-rproc 4a334000.pru: PRU rproc node pru@4a334000 probed successfully
[ 11.973707] remoteproc remoteproc1: 4a338000.pru is available
[ 11.973893] pru-rproc 4a338000.pru: PRU rproc node pru@4a338000 probed successfully

[ 61.264026] remoteproc remoteproc2: wkup_m3 is available
[ 61.271194] remoteproc remoteproc2: powering up wkup_m3
[ 61.271222] remoteproc remoteproc2: Booting fw image am335x-pm-firmware.elf, size 217168
[ 61.275721] remoteproc remoteproc2: remote processor wkup_m3 is now up

Editer et Modifier/boot/uEnv.txt pour désactiver la fonction HDMI.
###Disable auto loading of virtual capes (emmc/video/wireless/adc).
disable_uboot_overlay_video=1
disable_uboot_overlay_audio=1
Puis re-démarrer: sudo reboot now
Attention, c’est utile (uniquement) si on doit utiliser les pins du header P8 qui sont partagés avec l’HDMI. Voir les liens vers des tableaux « PinMux modes » en fin de post.

Information sur ma configuration :
ma disto
cat /etc/dogtag
BeagleBoard.org Debian Buster IoT Image 2020-04-06
cat /etc/debian_version
10.3
uname -a
Linux beaglebone 4.19.94-ti-r42 #1buster SMP PREEMPT Tue Mar 31 19:38:29 UTC 2020 armv7l GNU/Linux

Commençons les choses sérieuses

Télécharger BeagleScope (licence GPL v2), qui nous fourni les includes et libs pour pouvoir compiler et faire l’édition de lien, avec le Makefile.
git clone https://github.com/ZeekHuge/BeagleScope.git
si besoin, installer git : sudo apt-get install git
cd BeagleScope/
cd examples/firmware_exmples/pru_blinky/

Il y a des erreurs dans deploy.sh, on va faire le boulot en ligne de commande.
cd PRU_gpioToggle

Remplacer le fichier PRU_gpioToggle.c par celui sur ma page perso (avec wget, ci-dessous). Le code active le pin 27 du P9 (pin P9_27).
mv PRU_gpioToggle.c PRU_gpioToggle.c.old
wget elaurent.benaroya.free.fr/wordpress/BBB/PRU_gpioToggle.c

Vous pouvez (devez) éditer ce code. Ce qui est à retenir :

Le registre R30 est utilisé pour mettre à l’état haut ou l’état bas un pin configuré en sortie (pruout).
C’est un registre 32 bits.
On met alternativement le bit numéro 5 à 1 (état haut) et à 0 (état bas).
Le bit 5 du registre R30 correspond physiquement à P9_27.
Après avoir changé la valeur du bit 5 dans R30, on attend avec la fonction __delay_cycles pendant 100 millions de cycles, soit 1/2 secondes car le micro-controlleur fonctionne à 200 MHz.
Enfin, on boucle 60*5 fois, c’est dire pendant 5 minutes.
Ensuite, la commande __halt(); arrête le processus.

Attention, l’inclusion du fichier resource_table_empty.h est importante bien que celui-ci ne fasse pas grand chose.
Note importante : le code que je fournis est adapté de celui : beaglebone-pru-c

Compilation

1) d’abord définir la variable d’environnement PRU_CGT:
Créer les liens symboliques, à ne faire qu’une seule fois!
sudo ln -s /usr/bin/clpru /usr/share/ti/cgt-pru/bin/clpru
sudo ln -s /usr/bin/lnkpru /usr/share/ti/cgt-pru/bin/lnkpr

Puis :
export PRU_CGT=/usr/share/ti/cgt-pru
L’export peut être placé dans votre ~/.bashrc pour ne pas avoir à s’en occuper à chaque connexion au BBB.

2) Compiler
make clean
make

3) Copier le binaire dans le firmware
cd gen
cp PRU_gpioToggle.out gpiotoggle-fw
sudo cp gpiotoggle-fw /lib/firmware

Note importante : dans les versions « anciennes » du système d’exploitation, le nom du programme chargé dans le firmware est fixé : « am335x-pru0-fw » pour le PRU0 et « am335x-pru1-fw » pour le PRU1. Il faut donc remplacer la commande ci-dessous par :
cd gen
cp PRU_gpioToggle.out am335x-pru0-fw
sudo cp am335x-pru0-fw /lib/firmware

Le schéma électronique consiste à placer une LED et une résistance de 500 ohms environ, en série, entre P9_27 et P9_1 (DGND, digital ground).
Utiliser une LED jaune, rouge ou orange du fait de la chute de tension (entre 2 et 2.8 V contre 3.2 V au moins pour une bleue), sachant que la tension de sortie des gpio est de 3.3V!

Avec un résistance de 500 ohms, on obtient environ un courant de (3.3-2.3)/500 = 2 mA. C’est acceptable. Attention, le courant maximum délivré par chaque pin du gpio est de l’ordre de 4 mA à 8 mA, selon le pin : voir discussion dans GPIO current capacity?. C’est beaucoup moins qu’un Arduino, attention!!!

Configurer le pin P9_27 en sortie digitale (pruout)
config-pin

GPIO Pin Configurator
Usage:
   config-pin -c <filename>
   config-pin -l <pin>
   config-pin -q <pin>
   config-pin <pin> <mode>

config-pin -l P9.27
Available modes for P9_27 are: default gpio gpio_pu gpio_pd gpio_input qep pruout pruin
config-pin -q P9.27
Current mode for P9_27 is: default
config-pin P9.27 pruout
Current mode for P9_27 is: pruout

Lancer le programme sur le PRU0 (remoteproc0)
echo 'stop' > /sys/class/remoteproc/remoteproc0/state 2>/dev/null
echo "gpiotoggle-fw" > /sys/class/remoteproc/remoteproc0/firmware
echo 'start' > /sys/class/remoteproc/remoteproc0/state

La LED devrait se mettre à clignoter pendant 5 minutes.
Pour vérifier que les trois commandes ci-dessus se sont bien passées, on peut faire un dmesg. Si erreurs, problème!
dmesg | tail
[ 3105.812064] remoteproc remoteproc0: powering up 4a334000.pru
[ 3105.812358] remoteproc remoteproc0: Booting fw image gpiotoggle-fw, size 33556
[ 3105.812391] remoteproc remoteproc0: remote processor 4a334000.pru is now up
Note : comme indiqué ci-dessus, dans les versions plus anciennes de l’OS, le nom du programme dans le firmware est fixé,  la commande convenable est donc :
echo "am335x-pru0-fw" > /sys/class/remoteproc/remoteproc0/firmware

Approfondissement et liens externes

Pour le plaisir de mettre une image des headers P8 et P9 (c’est vendeur) :

Beaglebone Black Headers PinMux Modes

Les tableaux PinMux modes pour les headers P8 et P9
Celui-ci est très bien BeagleboneBlackPinMuxModes et les versions imprimables en pdf: P8 : P8 headers pdf et P9 : P9 headers pdf.
Dans la table du header P9, on a

P9 pin Offset mode 5 mode 6
P9_27 0x9A4 pr1_pru0_pru_r30_5 pr1_pru0_pru_r31_5

Dans cet extrait de la table, le pin 27 du header P9 correspond à pr1_pru0_pru_r30_5, qui indique le PRU 0, le registre 30 (output) sur le bit no 5.
Le mode 6, c’est la même chose mais en input, sur le registre R31. J’écris le bit no 5 parce que la numérotation des bits dans un nombre, en binaire, commence à 0. Donc le pin no 5 à 1 correspond à 0b0010_0000 en écriture binaire (sur 8 bits). En langage C, ce nombre peut s’écire 1 << 5 .

Voici un autre tableau équivalent, avec stabilotage : P9 headers.

Les pins GPIO pour la BeagleBone Black physiquement : The BeagleBone Black GPIO Pins ou gpio très complet (les figures en bas de la page).

Programmation des PRUs en C

Technique et bas niveau, mais vraiment intéressant, codage en C pour les PRUs : Beaglebone PRU Code in C

Sur les Remoteproc Remoteproc wiki

Super projet, proche de ce que je veux faire et qui a pour but d’acquérir de l’audio par le PRU, en temps réel, et de le transmettre au CPU qui le traite ou le joue : Using the Beaglebone Green Programmable Real-Time Unit with the RemoteProc and Remote Messaging Framework to Capture and Play Data from an ADC, lien parent du repo github.

Note sur le temps-réel

Il est important de comprendre que les PRUs permettent des traitements temps réel, car ce sont des micro-controlleurs dont on maîtrise totalement le fonctionnement en particulier celui des interruptions. Les versions « standards » de Linux ne permettent pas le temps réel parce qu’il peut se passer plein de trucs externes pendant l’exécution d’un programme. Il ne faut pas confondre temps réel et faible latence. Temps réel signifie qu’on peut prédire le temps d’excution d’un programme – de manière déterministe – indépendemment de la latence.

L’incontournable zeekhuge

Ce lien suivant est assez proche ce que j’ai exposé : l’application « blinky » : ptp_blinky. C’est assez complémentaire en fait.
Concernant les PRUs en général : working_with_prus_beagleboneblack_introduction_to_prus.

Conclusion

Dans ce post, j’ai exposé en détail comment compiler et exécuter un programme sur une « Programmable Real-time Unit » (PRU) de la BeagleBone Black. Le programme fait simplement clignoter une LED. J’espère que cette introduction à la programmation des PRUs vous sera utile et surtout vous donnera envie de réaliser des applications plus complexes, utilisant le SPI ou l’ADC par exemple, ou encore les timers.

ET Voilà!!!

Bien démarrer avec la BeagleBone Black Wireless (BBBw)

Voici quelques tips pour bien démarrer avec la BeagleBone Black Wireless. J’ai acheté ce petit bijou de technologie il y a peu et je partage avec vous mes premiers pas.
La BBB Wireless suppose des manips légèrement différentes pour la prise en main, par rapport à la BeagleBone Black. Il y a beaucoup en commun cela dit. Voici un guide pas à pas des étapes pour démarrer avec votre BeagleBone Black Wireless et la configurer. Après c’est à vous de jouer!

Les premiers pas, décrits dans la page getting-started de BeagleBoard.org sont les suivants:

Télécharger la dernière version de la distribution Debian de Linux sur la page latest-images.
– avec interface graphique (LXQT) https://debian.beagleboard.org/images/bone-debian-9.9-lxqt-armhf-2019-08-03-4gb.img.xz, version Debian 9 « Stretch » mars 2020,
– sans interface graphique (IoT = Internet of Things, si vous travaillez uniquement en ligne de commande) https://debian.beagleboard.org/images/bone-debian-10.3-iot-armhf-2020-04-06-4gb.img.xz, version Debian 10 « buster » avril 2020.

Ensuite,  graver l’image sur une carte micro SD; elle sera ensuite insérée dans le BeagleBone Black (BBB).

Pour cela, il faut installer BalenaEtcher, logiciel pour graver l’image de la distribution Debian de Linux sur la carte micro-SD.
Sous Linux/Debian (OS de votre ordinateur), c’est possible avec apt-get:
sudo apt-get install balena-etcher-electron
Il est également possible de télécharger un installeur:  balenaEtcher.

BalenaEtcher permet de graver l’image du système d’exploitation sur la carte SD.  Il y a un petit trick sous Linux. Dans un terminal, on exécute directement:
balena-etcher-electron
On peut avoir le message d’erreur suivant:
/usr/bin/balena-etcher-electron: ligne 3: /usr/bin/balena-etcher-electron.bin: Aucun fichier ou dossier de ce type
La solution consister à exécuter:
/opt/balenaEtcher/balena-etcher-electron
voir la note dans https://github.com/balena-io/etcher/issues/3074

Ensuite, dans  balena-etcher, on sélectionne l’image Linux téléchargée et le disque contenant la carte mirco-SD, enfin on « flash »! Cela peut prendre un certain temps (4 Go).

Personnellement, j’utilise un adaptateur de carte SD vers USB, pour brancher la carte micro-SD sur l’ordinateur, ce qui est bien pratique.

Étape suivante: insèrer la carte mirco-SD dans le BBB (uSD dans l’image ci-dessous). Puis brancher la BBB sur un port USB de votre ordinateur (avec un câble micro USB inséré dans « USB client » sur la BBB)  . Attention, avant et pendant l’allumage, il faudra appuyer pendant quelques secondes sur le bouton « boot button » pour démarrer sur la carte SD (l’image ci-dessous est une BBB standard, mais la connectique est similaire):

Noter que le démarrage (boot) de la BBB peut prendre quelques minutes.

Étape: se connecter au réseau Wifi local

Cette étape est spécifique à la BeagleBone Black Wireless, dans laquelle le port Ethernet est remplacé par la Wifi.

Normalement, après avoir allumé la BBB, un nouveau réseau Wifi devrait être activé sur votre ordi. La BBB Wireless fonctionne en mode serveur Wifi.

Si votre Beagle comprend le WiFi, un point d’accès appelé « BeagleBone-XXXX » où « XXXX » varie selon les cartes. Le mot de passe du point d’accès est par défaut « BeagleBone ». Votre Beagle doit exécuter un serveur DHCP qui fournira à votre ordinateur une adresse IP dans la plage 192.168.8.x et se réservera 192.168.8.1.

Il faut donc activer, sur votre ordinateur, la connexion Wifi « BeagleBone-XXXX », pour se connecter à la BBB Wireless. Ensuite, ouvrir un terminal (sous Linux ou Mac OS, sous Windows utiliser Putty) et se connecter au BBB avec la commande:
ssh debian@192.168.8.1
login: debian!!!
mot de passe: temppwd (normalement c’est indiqué)

Étape suivante: se connecter au réseau local Wifi

Cette étape est aussi spécifique à la BeagleBone Black Wireless.
C’est très bien décrit ici, (en Anglais), pas à pas. Je ne traduis pas là.
L’objectif est de connecter la BBB à la Wifi de votre box (Livebox, Freebox ou autre). Vous aurez à identifier votre box dans le tuto et à entrer le mot de passe. Après, vous pourrez vous connecter directement à la BBB Wireless avec la Wifi « normale ».
Pour trouver l’adresse ip de votre BBB sur le réseau Wifi, taper
ifconfig
Vous obtenez quelque chose comme ça:

Entouré en rouge, dans wlan0, après inet vous avez l’adresse ip locale de la BBB, 192.168.1.25 dans mon cas. Cette adresse commence par 192.168 (en général 192.168.0.xxx ou 192.168.1.xxx selon la box).
Vous pouvez  vous déconnecter de la BeagleBone:
exit
Sur votre ordinateur, se déconnecter du Wifi de la BeagleBone et se reconnecter à la box si utilisation de la Wifi (je suis connecté en Ethernet).
Pour vous reconnecter à la BBBw:
ssh debian@192.168.1.25
J’ai eu besoin de taper, comme indiqué,
ssh-keygen -f "/home/benaroya/.ssh/known_hosts" -R "192.168.1.25"
(je ne détaille pas la raison) puis retaper ssh debian@192.168.1.25
Noter que la commande suivante fonctionne également:
ssh debian@beaglebone.home
Du coup, on n’utilisera plus la BBB Wireless en serveur Wifi, mais la connexion est simplifiée.

Étape suivante: démarrer directement sur la carte SD (sans appuyer sur le boot button!)
C’est décrit, en Anglais, ici BeagleBone Black Wireless: Boot from SD card by default.
Vous trouverez une explication similaire, in French, dans le fichier bootingonsdcard. C’est un peu différent parce que nous avons « booté » sur la carte SD.

Élargir la carte SD de plus 4 Go

Pour une carte micro-SD de plus de 4 Go, il faut faire la manipulation suivante. Par défaut, il y a une limitation à 4 Go sur la BBB, ce qui est dommage quand on a une carte SD de 32 Go, comme moi.
La solution:
Le script « grow_partition.sh » permet de faire ça.
sudo /opt/scripts/tools/grow_partition.sh
sync
Si problème, le script est accessible dans le repo github https://github.com/RobertCNelson/boot-scripts/blob/master/tools/grow_partition.sh Je remets le script à disposition
Ensuite, il faudra redémarrer la BBB. Note: pour redémarrer un Linux en ligne de commande:

sudo reboot now

2 TIPS

Vérifier la date avec la commande « date » (une date mal réglée peut causer des problèmes d’update parfois):
date
Changer de fuseau horaire
timedatectl set-timezone Europe/Paris
ou pour nos amis Canadiens
timedatectl set-timezone America/Toronto
Nettoyer le système,
sudo apt-get clean
sudo apt-get autoremove
sudo apt-get update

Discussion :

La BeagleBone Black est intéressante pour les systèmes embarqués. Elle contient un micro-processeur Cortex-A8 à 1 Ghz (jeu d’instructions ARMv7) et deux microcontrôleurs PRU 32-bits (Programmable Real-time Unit) à 200 Mhz.
Par rapport à la Raspberry Pi, elle possède un autre avantage, la possibilité d’installer différentes distributions de Linux (Debian, Ubuntu) ou un Androïd (entre autres). L’OS standard de la Raspberry Pi (RPI), Raspbian, est une version adaptée de Debian.
L’avantage de la RPI est indéniablement la RAM (1 Go à 4 Go pour la RPI 4 contre 512 Mo pour la BBB) et ça peut faire une vraie différence pour des programmes gourmands en mémoire. Par ailleurs, la connectique USB est beaucoup plus intéressante. En mode ordinateur mono-carte, avec un écran, un clavier et une souris, utiliser une Raspberry Pi fait sens.
Concernant la BeagleBone Black Wireless, par rapport à la BBB standard, la Wifi est intéressante, pour installer des programmes facilement (apt-get install). Après est-ce que la différence de prix (de l’ordre de 20 €) se justifie? Vous me direz qu’on peut toujours ajouter un dongle USB sur la BBB. Mais il n’y a qu’un seul connecteur USB, donc le hub USB devient obligatoire, pas vraiment pratique.
J’utilise la BBBw branchée sur mon PC via le client USB (comme pour un Arduino), voulant explorer les possibilités de traitements temps-réel sur du son. Pour le moment, je suis content de mon achat. J’ai galéré quelque peu pour l’installation et la mise en place. J’espère que ce post permettra de vous aider et vous guider dans la prise en main.

ET VOILA!!!!

Comment classifier des images sur une Raspberry pi 3? TensorFlow Lite

Bonjour à tous,

Dans mon précédent post, j’explique comment installer TensorFlow 2 sur Raspberry Pi (RPI).

Je me suis rendu compte qu’en fait, il suffit d’installer TensoFlow Lite pour faire de la classification d’image à partir de réseaux de neurones pré-entraînés.

L’avantage, c’est que l’installation est beaucoup plus « lite » et que c’est très simple.

Tout est expliqué (en Anglais), là : TensorFlow Lite Python classification example with Pi Camera .

Et l’installation de TensorFlow Lite est expliquée ici : Python quickstart .

Le seul « trick » que je pourrais ajouter, c’est que perso, ce coup là j’ai utilisé Miniconda pour me créer un environnement virtuel avec Python 3.6 . J’en parle un peu dans mon précédent post. Dans ce cas, « pip install numpy » (dans les requirements.txt) ne marche pas, alors que « conda install numpy » fonctionne.

On peut lancer le code pour la classification automatique d’image :

python3 classify_picamera.py --model /tmp/mobilenet_v1_1.0_224_quant.tflite --labels /tmp/labels_mobilenet_quant_v1_224.txt

C’est vraiment super !!!

Pour comprendre, TensorFlow Lite prend quelques centaines de millisecondes pour classifier une image provenant du flux vidéo, tandis que TensorFlow mettra plusieurs secondes. Cela est dû en partie au fait que le modèle Lite est quantifié sur 8 bits (sauf erreur de ma part). Au lieu de nombres à virgule flottante (float) codés sur 32 bits, on utilise des entiers sur 8 bits, ce qui réduit la taille (en octets) du modèle et surtout accélère considérablement le temps de calcul. Les résultats sont un peu moins précis en principe.

Voici une version un peu modifiée de la démo classify_image.py qui permet de classifier une seule image :

curl -O https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_1.0_224_quant_and_labels.zip
unzip mobilenet_v1_1.0_224_quant_and_labels.zip
python classify_image.py --model mobilenet_v1_1.0_224_quant.tflite --labels labels_mobilenet_quant_v1_224.txt --image monimage.jpg

Les deux premières lignes téléchargent et dé-zippent le modèle. « classify_picamera.py » est remplacé par « classify_image.py ». Notez l’option supplémentaire –image qui permet de fournir un fichier image au lieu d’utiliser la camera du RPI.

Et voilà!!!

Comment installer TensorFlow version 2 sur Raspberry Pi : la compilation croisée ?

classifier des images Sur ma Raspberry pi 3 avec un réseau de neurones profond sous Python 3

L’objectif est de classer des images depuis une Raspberry 3, en utilisant la camera « rapstill » dédiée. Une application potentielle est la prise de photos, en envoyant à un serveur distant uniquement les images d’animaux (par exemple). Nous souhaitons, pour cela, utiliser des outils du « Deep Learning », avec des réseaux de neurones profonds pour la classification des images.

A noter que la Raspberry 3 B+ a des ressources limitées en terme de mémoire vive [1 Go de RAM]. De plus, son processeur de type ARM est différent de celui sur un PC (x86).

premier essai d’installation de tensorflow et de keras

On travaille sous python 3.x sur une Raspberry Pi 3 B+.

Keras est un paquet Python qui permet de créer, d’entraîner et de tester des réseaux de neurones profonds (DNN = Deep Neural Network). Keras est intéressant car il y est facile et rapide de mettre en œuvre des DNNs par rapport aux alternatives. A la base, Keras est une couche haut niveau qui utilise des logiciels d’optimisation comme TensorFlow ou Theano. Dans cet article, on se concentre sur TensorFlow avec la « sur-couche » Keras « au-dessus ».

L’installation de TensorFlow version 1, sur la Raspberry, se fait avec l’outil « pip ». Malheureusement, ça bloque côté Keras et en particulier sur la compilation du paquet « scipy » version 1.4.1 (scientific python).
Pour compiler scipy depuis les sources, sur la Raspberry, il est conseillé d’augmenter la taille du swap (définition du swap, comment augmenter sa taille), mais les 1Go de RAM ne suffisent pas.

Le paquet compile pendant une heure et demi, puis plus rien : pas de message d’erreur, mais il ne se passe plus rien. En googlant un peu, je me rends compte que je ne suis pas le seul à galérer sur le problème.

J’abandonne momentanément mon objectif.

TensorFlow 2

A travers d’autres projets, je commence à utiliser TensorFlow dans sa version 2. Je code par exemple une factorization en matrices non négatives (NMF) en utilisant TensorFow (TF) comme un outil d’optimisation performant. Génial.
Le truc vraiment génial, c’est que TensorFlow 2 intègre entièrement Keras.

Je comprends que si j’arrive à installer TensorFlow 2 sur la Raspberry Pi (RPI), j’ai gagné la partie, ou du moins je marque un bon point.

classification d’images de la base imagenet

Parallèlement, sur mon PC de bureau, je m’intéresse à la classification d’images avec TF 2/ Keras. Mieux vaut tard que jamais! J’utilise la base d’images ImageNet, qui est géniale car elle contient 1000 classes d’objets visuels. Pour la classification, j’utilise Inception v3, qui est intégré à TF 2 (tf.keras.applications.InceptionV3). C’est un gros réseau de neurones profond.
Les résultats sont bluffants.
En passant, je remarque qu’il existe une version light du modèle Inception v3 (entre autres!) avec TF Lite, ou du moins la possibilité d’en créer.
Je range ça quelque part dans ma mémoire.

Pour la petite histoire, J’ai montré les performances de classification avec la base ImageNet et Inception, à ma compagne le soir même. Pas vraiment enthousiaste. Moi je trouve ça génial. Je sais que c’est un des premiers gros succès du Deep Learning (apprentissage profond).
Pour se faire une idée, lorsque je joue à pile ou face, j’ai deux cas. Le hasard me donne une probabilité de 1/2 = 50% par face.
Donc si je suis capable de prédire un peu mieux le résultat (par exemple si la pièce est bizarrement faite et que le jeu est pipé, c’est un peu tordu mais bref), prédire ne serait-ce qu’à 51% d’accuracy, je fait mieux que le hasard et ça déjà c’est très fort. ça ne paraît pas comme ça, mais ça fait une vraie différence. Au passage, l’accuracy est un terme anglais qui désigne le pourcentage d’items correctement classés.

Dans la base de données ImageNet,  il y a 1000 classes (explore), regroupées de manière hiérarchique dans les macro-classes suivantes :

  • Plant, flora, plant life,
  • Geological formation, formation,
  • Natural object,
  • Sport, athletics,
  • Artifact, artefact,
  • Fungus,
  • Person, individual, someone, somebody, mortal, soul,
  • Animal, animate being, beast, brute, creature, fauna,
  • Misc.

Pour 1000 classes, le hasard c’est 1/1000, soit 0.1 %. Avec le Deep Learning, on atteint des résultats de l’ordre de 70 à 80% d’accuracy, sur un ensemble de TEST (c-a-d différent de l’ensemble d’apprentissage). Passer de 0.1% à 70%, c’est hallucinant!

Exemple artichaut ! (image trouvée sur le net)

Résultat avec Inception v3

artichoke,		probability = 92.3%
cardoon,		probability = 0.4%
jack-o'-lantern,	probability = 0.1%
grocery_store,		probability = 0.1%
Dutch_oven,		probability = 0.0%
retour au Raspberry
les versions de Python

Il est possible d’installer Miniconda sur la RPI, à la main. C’est une version light d’Anaconda et qui permet de créer des environnements virtuels pour python de manière simple. Avec un environnement virtuel, on peut installer python et pleins de paquets/modules, modifier des bouts de code, faire port-nawak. ça n’est pas grave. Il suffit d’effacer l’environnement et le système est indemne. C’est le principe de la virtualisation.
Avec Miniconda pour la RPI, la version de Python est 3.4. Or TF 2 nécessite une version de Python supérieure ou égale à 3.5.
Il est possible d’installer Python 3.6 avec Berryconda.
Pour cela, taper dans un terminal de votre Raspberry:
conda config --add channels rpi
puis pour créer l’environnement avec Python 3.6
conda create -n py36 python=3.6
Pour activer environnement virtuel avec python 3.6
conda activate py36
pour en sortir
conda deactivate [et pas deSactivate]

J’ai fait le choix d’installer localement Python 3.7, non disponible avec Miniconda.
Pour cela, j’ai compilé les sources sur la RPI. On va suivre l’article Installing Python 3.7.2 on Raspbian :
Dans un terminal, installer les paquets nécessaire à la compilation
sudo apt-get update -y
sudo apt-get install build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev -y

Télécharger les sources [note: la marche à suivre est la même pour une autre version de Python, en fournissant l’url adéquate pour wget]
wget https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
tar xf Python-3.7.2.tar.xz
cd Python-3.7.2

Les compiler : 1ère option, globale
./configure
make
make install
2ème option, locale.
créer un répertoire  « py37 » dans « /home/pi » puis
./configure --prefix=/home/pi/py37
make
make install

Dans le second cas, pour utiliser python3 et pip3, c-a-d pour activer python 3.7, il faudra taper dans la console:
export PATH=/home/pi/py37/bin:$PATH
et utiliser pip3 et python3
Note: on pourrait placer une fois pour toute la ligne "export ..." à la fin du fichier "/home/pi/.bashrc"
Si cela vous paraît obscure, utilisez la première solution (globale).

Le coup de bol

En cherchant à installer TF 2 sur Raspberry 3, je suis tombé, avec un peu de chance, car il est tard, sur le repo github de Leonardo Lontra alias lhelontra. [github est un dépot de programmes/codes sources, énorme et très très utilisé.]

Le code source « https://github.com/lhelontra/tensorflow-on-arm » permet de faire la compilation croisée.
Cela signifie qu’on va pouvoir compiler TF sur une machine puissante, comme mon PC de bureau et le résulat sera utilisable sur la RPI et non sur mon PC. On parle de cross-compilation ou compilation croisée. Contrairement au Rapsberry, mon PC a 8 Go de mémoire et un processeur i5 avec 4 coeurs (c’est un PC, sous linux, datant de 2016).

Bon je spoile : la compilation croisée a duré 7 heures et ça a marché!!! Je viendrais tout de suite à la marche à suivre.

Mais en écrivant ces lignes, je m’APRECOIS qu’il y a des versions cross-compilées déjà disponibles dans le repo github.
Quel imbécile je fais!

Alors ce qu’on peut faire, c’est allumer son RPI et lancer un navigateur web et un terminal.
Dans le repo (https://github.com/lhelontra/tensorflow-on-arm), il suffit de cliquer sur l’onglet « releases » (voir image ci-dessous) ou bien taper dans la barre de navigation https://github.com/lhelontra/tensorflow-on-arm/releases .


Ensuite, en dessous de TENSORFLOW 2.0, on clique sur « tensorflow-2.0.0-cp37-none-linux_armv7l.whl » et on l’enregistre.


dans Le nom de ce fichier Wheel, « tensorflow-2.0.0 » c’est pour TF 2.0.0 (!), « cp37 » pour Python 3.7 et « linux_armv7 » c’est pour une architecture linux avec un processeur ARM 7, qui correspond à l’architecture et le processeur du Raspberry pi 3. Pour comprendre, sur un PC le processeur peut-être un i3 ou un i5 ou un pentium. Dans tous les cas, c’est un processeur « x86 ».

Installation de tensorflow 2 sous RPI

On ouvre un terminal dans le Raspberry et on se place là où tensorflow-2.0.0-cp37-none-linux_armv7l.whl a été téléchargé (en général, /home/pi/Downloads),
taper
cd /home/pi/Downloads
puis
pip3 install tensorflow-2.0.0-cp37-none-linux_armv7l.whl
Et c’est tout! Job’s done.

La compilation croisée

SUR NOTRE SUPER PC, sous LINUX :

On va installer « DOCKER » (outil de virtualisation pour le système en entier). Cela permettra d’éviter des conflits entre des librairies ou des composants manquants par exemple. J’ai fait un essai sans docker et ça a planté au bout de 20 minutes. Donc avec Docker c’est mieux.
Pour installer Docker (voir https://docs.docker.com/install/linux/docker-ce/debian/).
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
Perso, j’ai installé docker avec dpkg, pour une raison qui m’échape (il était vraiment tard!), mais les commandes ci-dessus doivent fonctionner.

ENSUITE,
On télécharge le code source du repo de lhelontra, avec git:
sudo apt-get install git -y [on installe l’outil git si nécessaire]
git clone https://github.com/lhelontra/tensorflow-on-arm.git
cd tensorflow-on-arm

On lit ce qui est indiqué dans la section « Cross-compilation » du repo de lhelontra :

On ajoute l’architecture ARM aux repos debian:
sudo dpkg --add-architecture armhf
la seconde ligne est un peu problématique parce qu’on veut ajouter la ligne
deb [arch=armhf] http://httpredir.debian.org/debian/ buster main contrib non-free
dans le fichier « /etc/apt/sources.list »
La solution choisie, bien que très mal, est de passer en ROOT avant de taper la commande :
sudo su -
echo "deb [arch=armhf] http://httpredir.debian.org/debian/ buster main contrib non-free" >> /etc/apt/sources.list
exit

Ensuite
cd build_tensorflow/
sudo docker build -t tf-arm -f Dockerfile .      [utiliser sudo et ne pas oublier le .]

Avant de lancer la dernière commande, on peut éditer le fichier de configuration « rpi.conf » qui se trouve dans le sous-répertoire « configs ».
On vérifie la ligne
TF_VERSION= »v2.0.0″ [version de tensorflow]

On lance la compilation, en remarquant qu’on peut choisir la version de Python (--env TF_PYTHON_VERSION=3.7)
sudo docker run -it -v /tmp/tensorflow_pkg/:/tmp/tensorflow_pkg/ --env TF_PYTHON_VERSION=3.7 tf-arm ./build_tensorflow.sh configs/rpi.conf

La compilation peut durer plusieurs heures (7 heures pour moi), donc à lancer la nuit de préférence.
On obtient finalement un fichier « tensorflow-2.0.0-cp37-none-linux_armv7l.whl » dans le répertoire /tmp/tensorflow_pkg/

On le recopie ensuite sur le Raspberry Pi.
Une fois sur le RPI, il restera à faire un « pip3 install tensorflow-2.0.0-cp37-none-linux_armv7l.whl » pour l’installation sur le RPI, comme indiqué plus haut.

L’intérêt de discuter de la compilation croisée, outre de comprendre un peu le dessous des cartes, c’est que ça peut être utilisé pour créer le fichier wheel pour une autre architecture comme le Beagle Bone Black par exemple (choisir le fichier de config « beagle_black.conf »), pour laquelle il n’y a pas de « release ».

Pour finir, ce post décrit comment installer TensorFlow 2 sur une Rapberry pi 3. Dans sa version la plus simple, il suffit d’installer, sur le RPI, Python 3.7 et de télécharger le fichier wheel adéquat pour TF 2 depuis https://github.com/lhelontra/tensorflow-on-arm/releases .
On peut aussi cross-compiler sur un PC plus puissant, sous linux, avec pour cible d’autres appareils comme le Beagle Bone Black, ou pour utiliser une autre version de Python (>=3.5) pour la RPI.

Et voilà!