Ici nous vous informerons des dernières nouvelles concernant l'avancement de nos projets et autres !
Bonne lecture !
11 juillet 2025
C’est Robotronik Phelma qui nous a aiguillé vers les cartes SD à la coupe. Alors, nous prenons notre moteur de recherche favori trouvons deux-trois informations prometteuses sur les cartes SD :
Le protocole SDIO ressemble au protocole de communication SPI, avec 4 lignes de données et des commandes normalisées pour commander la carte SD (probablement les mêmes qu’en SPI). C’est surtout une vitesse de transfert 4 fois plus élevée pour la même fréquence d’horloge qui nous intéresse. Vous trouverez assez facilement des documents décrivant le protocole SDIO, En voici un au hasard.
Concernant le projet no-OS-FatFS-SD-SDIO-SPI-RPi-Pico, le README est particulièrement encourageant : il annonce des vitesses de lecture et d’écriture supérieures à 10 Mo/s. Maintenant, nous voulons tester ça !
Côté brochage de la carte, nous n’arrivons pas à trouver la description dans la norme, mais de nombreux sites proposent tous le même brochage, que voici :
C’est un commentaire dans le code qui nous explique comment raccorder l’adaptateur SD avec le microcontrôleur :
/* SDIO Interface */
static sd_sdio_if_t sdio_if = {
/*
Pins CLK_gpio, D1_gpio, D2_gpio, and D3_gpio are at offsets from pin D0_gpio.
The offsets are determined by sd_driver\SDIO\rp2040_sdio.pio.
CLK_gpio = (D0_gpio + SDIO_CLK_PIN_D0_OFFSET) % 32;
As of this writing, SDIO_CLK_PIN_D0_OFFSET is 30,
which is -2 in mod32 arithmetic, so:
CLK_gpio = D0_gpio -2.
D1_gpio = D0_gpio + 1;
D2_gpio = D0_gpio + 2;
D3_gpio = D0_gpio + 3;
*/
.CMD_gpio = 3,
.D0_gpio = 4,
.baud_rate = 125 * 1000 * 1000 / 6 // 20833333 Hz
};
C’est donc l’heure du shopping ! Nous cherchons un adaptateur de carte SD, mais qui support le protocole SDIO. Attention, certains adaptateurs n’offrent que le protocole SPI ! Nous sommes en amont du projet et nous ne sommes pas prêts à faire des compromis là-dessus.
Après quelques minutes de recherche, nous nous agaçons. Ce truc va nous coûter des sous, mettre du temps à arriver... Bref, nous trouvons une autre solution, pas forcément des plus élégantes :
Non, nous n’avons pas soudé les fils directement sur une carte SD, ceci aurait été problématique pour la lire sur un ordinateur. Il s’agit d’un adaptateur de carte SD vers micro SD. En utilisant des cartes micro-SD, nous pouvons les connecter à la plaque de test ou les sortir pour les lire sur le PC. Pile ce qu’il nous fallait.
Nous prenons le code de no-OS-FatFS-SD-SDIO-SPI-RPi-Pico et modifions l’exemple SDIO pour mesurer la vitesse d’écriture. Nous sommes d’abord ravis de voir apparaître les fichiers avec le bon contenu sur la carte SD. Puis en regardant les vitesses d’écriture, le doute s’installe :
Écrit: 38 octets en 46995 us
Écrit: 4066 octets en 30379 us
Écrit: 65482 octets en 28264 us
Comme si, plus nous écrivions de données, plus le temps total de l’opération diminuait. Ce qui n’est pas logique.
Des essais suivants montrent qu’il y a :
Mais globalement nous atteignons une vitesse de l’ordre de 2 Mo/s, et ça, c’est top !
Aviez-vous remarqué que dans le nom du projet no-OS-FatFS-SD-SDIO-SPI-RPi-Pico, il y avait FsFAT ?
Bref, notre code USB et le code SDIO utilisent la même bibliothèque. À nous de créer un bout de code pour que la bibliothèque gère les deux supports. Si vous vous rappelez de notre article précédent, vous vous souvenez que :
Nous reprenons la structure décrite dans diskio.c de FsFAT et sélectionnons la "bonne" fonction disk_* en fonction du numéro du disque. Les disques 0 et 1 sont des cartes SD et les fonctions disk_* appellent leurs homologues SDIO_disk_* tandis que les disques 2 à 9 sont des périphériques USB et les fonctions disk_* appellent leurs homologues USB_disk_*.
Au lieu de nous contenter d’une ou deux écritures sur la carte, nous lançons des écritures de 64 ko sur la carte SD et sur la clé USB. Nous restreignons l’acquisition à 1 minute et obtenons le graphique suivant.
L’écart, en termes de performance, est sans appel.
Si nous réalisons le même exercice mais juste avec les écritures sur la carte SD, nous obtenons beaucoup plus de points en une minute, ce qui permet de valider la stabilité des résultats.
Nous observons bien quelques pics de lenteurs autour de 0,5 à 1 Mo/s mais la vitesse moyenne d’écriture se situe bien autour de 2,0 Mo/s, ce qui est une très bonne nouvelle.
Écrire à la fois sur la carte SD et sur la clé USB n’est pas le plus utile ici ! Ce qui nous intéresse vraiment, c’est d’avoir la pile USB hôte fonctionnelle avec la capacité d’écrire des logs massivement !
11 juillet 2025
Alors, oui, nous avons une piste pour régler nos problèmes de communication, surtout que l’USB nous avait été chaudement recommandé à la coupe.
Mais nous avions un autre souhait pour notre robot, avoir des logs. Mais pas juste une LED qui s’allume en cas de soucis, des vrais logs, des gros fichiers avec plein de données dedans !
Nous voyons que notre code de démonstration supporte la classe "Mass Storage", nous sommes donc sur la bonne voie. Mais que se passe-t-il lorsque nous connectons une clé USB ? Eh bien, pas grand-chose :
A device with address 1 is mounted
A device with address 1 is unmounted
Alors comment aller plus loin ?
La bibliothèque TinyUSB propose une liste de fonctions pour gérer les périphériques "Mass Storage", accessible dans le fichier msc_host.h. Mais en observant ces fonctions, il n’y a rien qui ressemble à ouvrir ou fermer un fichier.
Les fonctions USB vont permettre de lire ou d’écrire une plage d’octet sur le périphérique, comme si nous accédions à une mémoire — ce qui est le cas. C’est très bien pour écrire une donnée brute, mais pour créer des fichiers qui seront lisibles sur un ordinateur, il manque toute une couche logicielle. Ces fonctions USB sont inspirées du protocole SCSI dont nous avons la liste compréhensible des commandes. Et rien là-dedans ne permet d’ouvrir, lire ou écrire des fichiers. Il s’agit plutôt de fonctions pour copier des morceaux de mémoire.
Pour gérer des fichiers, il faut un système de fichier. Un système de fichier est une organisation de la mémoire qui contient :
Sur microcontrôleur, il n’y a pas beaucoup de systèmes de fichier qui seraient à la fois simples et reconnus par un ordinateur. Le principal candidat est FAT/exFAT. Il s’agit en réalité d’une famille de système de fichiers (FAT12, FAT16, FAT32, exFAT). FAT12, le plus ancien date de 1980 et était utilisé sous QDOS, l’ancêtre de MS-DOS tandis que exFAT est encore couramment utilisé sur les cartes SD. Ces systèmes de fichier regroupent la mémoire par blocs pour faciliter sa gestion.
Si nous parlons d’une famille de système de fichier, c’est qu’au lieu d’implémenter la spécification, nous utilisons une bibliothèque qui gère toute cette famille. Cette bibliothèque, c’est FsFAT !
L’interface en TinyUSB et FsFAT se résume à quelques fonctions. Chacune de ces fonctions prend en argument le numéro du "disque" sur lequel effectuer les opérations.
Le code à étudier est certainement l’explorateur de fichier fourni dans les exemples de TinyUSB.
C’est un détail, mais FsFAT demande une fonction qui renvoie la date actuelle. Si vous n’avez pas d’horloge à l’heure sur votre microcontrôleur, Vous pouvez renvoyer n’importe quelle date, mais c’est cette date qui apparaîtra comme date de création ou de modification du fichier.
Côté architecture logicielle, nous avons "juste" rajouté la couche FsFAT à notre projet précédent :
Nous étions un peu là pour ça, non ?
Pour écrire dans un fichier, la procédure est la suivante :
Rien de sorcier, mais il y a une petite subtilité. Les chemins sont sous cette forme :
[disque#:][/]répertoire/fichier
Les crochets [...] indiquent des éléments facultatifs. Si vous n’indiquez pas de disque, FsFAT supposera que vous cherchez à écrire sur le disque 0. Dans notre cas, ceci nous a joué un tour. Si nous connections la clé USB directement sur le Raspberry Pi Pico, elle obtenait l’adresse 1. Nous avions codé en dur l’adresse du disque dans nos fonctions disk_*. Mais en ajoutant un hub, l’adresse de la clé passait à 2 et plus rien ne marchait. C’est embêtant au début, mais très flexible par la suite. Vous pouvez gérer plusieurs clés USB par exemple. Imaginez en garder une en permanence sur le robot et une qui reçoit automatiquement les derniers logs lorsque vous la branchée.
Pour plus de détails, lisez la bonne documentation.
Les performances ? Pas terribles, nous ne dépassons pas les 64 ko/s, ce qui est aussi la limite trouvée par rppicomidi dans son projet pico-usb-host-msc-demo... D’après le projet de rppicomidi, c’est la conception de l’USB sur le Raspberry Pi Pico qui n’est pas faite pour obtenir de bonnes performances en mode "hôte". De notre côté, nous n’avons pas les compétences pour nous prononcer sur la cause, mais nous réalisons le même constat...
Alors 64 ko/s, ça paraîtrait OK pour du log, mais ça veut dire que nous utilisons un cœur complet pour écrire sur la clé, et que notre ressource USB ne fait qu’écrire les logs, Or nous comptons sur l’USB pour la communication intra-robot, pas question de partir sur une solution qui semble déjà montrer ses limites...
7 juillet 2025
Après plusieurs participations, nous avons observé des problèmes de communication I2C entre nos cartes équipées de Raspberry Pi Pico. Nous avions deux choix :
Nous avions tenté, avec plus ou moins d’acharnement et pas trop de succès, le premier choix. La difficulté résidant dans la reproduction du défaut. On peut toujours débrancher un fil, mais le débranche-t-on le bon fil ? au bon moment ? Bref, nous n’avons rien produit de concluant.
Pour la seconde solution, nous faisons l’hypothèse que les problèmes de communication viennent des perturbations électromagnétiques. Alors qu’est-ce qui permettrait de se protéger des perturbations électromagnétiques ?
Et quel protocole (relativement) bien supporté par tout microcontrôleur moderne coche ces cases ? Devinez... L’USB !
De son nom, Universal Serial Bus, nous pourrions croire que le protocole se rapproche d’une liaison UART un peu évoluée, mais il n’en est rien. Le protocole est organisé autour d’un "hôte" (host) et des périphériques (devices). La norme USB décrit un empilement de protocoles, de la définition du 0 et du 1 sur le bus à la définition des classes de périphériques (Devices class) qui vont jusqu’à spécifier, de manière flexible, les cas d’utilisation de l’USB.
Ces classes de périphérique permettent de prendre en charge un grand nombre de périphérique différents sans développer de pilote spécifique à chaque fois. Quelques exemples de classes :
Pour une liste plus complète, wikipédia en anglais propose quelque chose de compréhensible.
Vouloir utiliser l’USB sans utiliser l’une des classes existante demande un effort considérable ! Bref, nous ne le conseillons pas !
La flexibilité du protocole USB en fait sa force mais crée une complexité qui fait que, même si nous maîtrisions parfaitement le protocole, nous ne pourrions le résumer en un billet de blog. Le meilleur résumé que nous pouvons vous proposer en ligne est USB in a Nutsheel. En français, j’ai le souvenir d’une revue qui présentait l’USB à travers une série d’articles, mais je n’en trouve pas la trace.
Et nos microcontrôleurs, dans tout ça ? La plupart des cartes pour développer sur microcontrôleur proposent un port USB, mais nous les classerons en 3 familles :
Les 2 premières familles peuvent envoyer des données sur le bus USB sans soucis. La première sera restreinte à la classe CDC, tandis que la seconde sera plus flexible et pourra, par exemple, émuler un clavier ou une souris.
Mais seuls les microcontrôleurs appartenant à la 3e famille peuvent coordonner le bus USB. La solution "simple" est de laisser un ordinateur embarqué assurer ce rôle. Mais ce n’est pas notre souhait. Le Raspberry Pi Pico, basé sur le RP2040 est de la 3e famille, qui support hôte et périphériques. Notons qu’ayant qu’un seul port, un seul des rôles USB (hôte ou périphérique) peut être actif à un moment donné.
Pour tester la fonctionnalité hôte USB, nous utilisons le code de démonstration fourni dans pico-example : host_cdc_msc_hid.
L’exemple de la fondation RaspberryPi marche bien. Ce qui nous a pris du temps :
Si le port USB est pris, il faut récupérer les informations par un autre moyen. Nous utiliserons la liaison UART avec un convertisseur UART / RS232 puis un second convertisseur RS232/USB (parce que nous avions ceci sous la main).
Note : sur le montage ci-dessus, il manque encore un câble USB pour l’alimentation...
L’exemple permet de gérer 4 types de périphériques USB :
Côté architecture logicielle, nous en somme là :
Pour tester, nous commençons par relier un Raspberry Pi Pico avec un bête code printf("exemple\n") toutes les secondes à notre hôte USB. La connexion est détectée et les informations sont bien reçues !
TinyUSB Host CDC MSC HID Example
# Branchement d'un Rapsberry Pi Pico
CDC Interface is mounted: address = 1, itf_num = 0
Baudrate: 115200, Stop Bits : 0
Parity : 0, Data Width: 8
A device with address 1 is mounted
# Echo des données reçues
Exemple
Exemple
Exemple
# Déconnection du Raspberry Pi Pico
A device with address 1 is unmounted
CDC Interface is unmounted: address = 1, itf_num = 0
# Branchement d'un hub USB
A device with address 1 is mounted
# Branchement d'un Rapsberry Pi Pico sur le hub
CDC Interface is mounted: address = 2, itf_num = 0
Baudrate: 115200, Stop Bits : 0
Parity : 0, Data Width: 8
A device with address 2 is mounted
# Echo des données reçues
Exemple
Exemple
Exemple
# Déconnection du Raspberry Pi Pico
A device with address 2 is unmounted
CDC Interface is unmounted: address = 2, itf_num = 0
# Déconnection du hub USB
A device with address 1 is unmounted
29 juin 2025
Voilà un mois que la coupe 2025 s’est terminée. C’était pour nous une coupe très particulière. En effet, nous étions grandement impliqués dans les deux équipes "Riombotique", au point d’avoir décidé de ne pas réaliser de robot pour Poivron Robotique cette année. C’est une expérience totalement différente avec énormément de trucs chouettes et quelques écueils qui nous ont fait mal.
L’une de nos conclusions, c’est que nous aimons notre équipe "Poivron Robotique". Mais Poivron Robotique c’est quoi ? Notre équipe n’est pas la seule à se poser ce genre de questions existentielles, vous avez Les Karibou qui présentent leurs réflexions à ce sujet.
En très bref, Poivron Robotique est bâti sur deux axes : maîtriser les technologies que nous utilisons et écrire des articles les présentant. Le détail de nos réflexions se trouve sur notre page Présentation.
Poivron Robotique sera probablement présent à la coupe de France de Robotique 2026. Nous travaillons toujours - bien qu’avec moins d’acharnement - sur nos articles sur le déplacement d’un robot.
Après des échanges avec différentes équipes, nous allons troquer notre bus de communication I2C pour un bus USB. Ce qui amènera probablement un ou plusieurs articles sur l’USB. Nous cherchons également à stocker nos logs, pour enregistrer massivement ce que se passe sur le robot. Enfin, nous cherchons un moyen de mieux comprendre l’environnement du robot à partir des capteurs VL53L8CX. Nous avons bien quelques idées mais rien d’abouti pour l’instant.
L’été s’annonce chargé et j’espère que nous reprendrons le rythme de publication que nous avions les années précédentes !
15 février 2025
Nous profitons de cette nouvelle année pour présenter, tardivement, nos meilleurs vœux pour cette année 2025.
Après une année 2023-2024 bien chargée, nous levons un peu le pied, ce qui explique cette activité éditoriale bien plus faible.
Cependant, plus faible ne veux pas dire inexistante ! Nous préparons une série d’articles sur le déplacement des robots qui sera publiée sur ce site quand elle sera prête, et pas avant. Si vous êtes curieux, ou que vous souhaitez participer à la rédaction de ces articles, notre bouillon (qui commence à prendre forme) est en ligne sur ce le wiki Eurobot.
Nos projets se concentrent sur les activités du club robotique de Riom. Ces activités nous amèneront probablement à publier des articles mais pas les points d’avancement que nous partagions habituellement sur ce site...
Bref, nous sommes toujours là, mais moins actifs ici !