Tu vois Pokémon GO/Ingress ? Tu vois le fait de piquer des cônes de chantier quand t’es bourré·e ? Ben imagine un mélange des deux, une sorte de Pokémon GO/Ingress mais où tu peux piquer les points de contrôle pour les changer de place…
Au final, ce projet avance gentiment. J’ai continué à travailler dessus durant mes heures de libre, et je pense pouvoir dire que j’approche d’un joli prototype. Néanmoins, j’ai eu quelques écueils en cours de route, qui seront détaillés au fur et à mesure.
Il va y avoir beaucoup d’informations éparses dans cet article, et je me dis qu’il faudrait que je fasse un devlog régulier, si je souhaite réussir à me souvenir de tout.
Avant toute chose !
Je rappel que le projet possède son propre repo git. Le projet se voudra Open Source du début à la fin dans la mesure du possible, donc je vais essayer de tout bien documenter et mettre en place sur ce repo, avec des README qui tiennent la route (;.
Trouver un nom !
En général, lorsque je cherche un nom pour un projet, je me rends sur Google Translate, je tape quelques mots clés liés au projet, et je teste des langues « exotiques » et/ou que j’apprécie, comme le Russe, l’Arabe ou le Latin. Cette fois-ci n’a pas fait exception, j’ai cherché « cône de construction », et en me baladant un peu, je suis tombé sur le Gaélique, avec la tournure « còn togail ».
Néanmoins, après réflexion, le nom ne sonnait pas assez « sexy », et surtout pas assez facile pour une adoption par un public. Je suis donc resté avec le Gaélique, mais cette fois-ci en testant d’autres termes, comme « localisation », « chantier », trouver », … Je suis finalement arriver sur « lorg còn », qui signifie « localiser/trouver un cône », et une légère compression aura donné « Lorcòn » (prononcé \lɔʁkɔn\, « lore cône »). Et voilà !
Sinon, mon très cher Simon G. a proposé un chouette nom pour les cônes : « protocône ». Du coup, c’est adopté.
Prise en main de l’ESP32
Pour rappel, sur conseils d’une personne sur Telegram, j’ai acquis une ESP32 pour pouvoir faire joujou. Il faut savoir que ce machin est magique et contient à peu près tout : WiFi, Bluetooth, BLE, contact avec induction, effet Hall, … Je ne sais pas pourquoi je n’ai pas essayé de bricoler avec avant, mais c’est génial.
J’ai trouvé un site qui contient vraiment beaucoup de tutoriels et d’informations pour permettre d’apprendre, il est chouette et bien complet, je le mets donc ci-après :
Également, la documentation globale du constructeur est intéressante et complète : https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html#.
Faire fonctionner le GPS
La première étape concrète dans mon plan de route aura été de faire fonctionner le GPS. J’ai donc commandé un petit module GPS NEO6MV2, pour bricoler avec, car cela semblait la recommandation dans plusieurs tutoriels. La documentation est ici.
Première « difficulté », trouver la bonne bibliothèque, car il en existe deux, la TinyGPS, et la TinyGPSPlus – la dernière étant plus compacte et plus efficace à utiliser. La seconde « difficulté », il faut faire attention de remplacer l’utilisation de SoftwareSerial par HardwareSerial, car manifestement ça pose souci quand on transitionne d’Arduino à ESP32 – en tout cas je n’ai pas réussi à le faire fonctionner avec SoftwareSerial.
Le code de base consiste simplement à récupérer des données depuis le GPS, et à les afficher. Ensuite, il suffit d’explorer un peu les exemples de la bibliothèque, qui sont facilement adaptables.
#include <HardwareSerial.h> HardwareSerial ss(1); void setup(){ Serial.begin(9600); ss.begin(9600, SERIAL_8N1, 16, 17); } void loop(){ while (ss.available() > 0) { byte gpsData = ss.read(); Serial.write(gpsData); } Serial.println(); delay(1000); }
Concernant l’assemblage, et quelques détails additionnels, le site suivant m’a bien aidé :
Par contre, là où j’ai galéré, c’est pour avoir des data depuis le GPS… En gros, pour commencer à obtenir des data, le module tente de trouver des GPS, puis, une fois les GPS trouvés, va pouvoir calculer sa position. Ce que je ne savais pas, c’est que ce module a des difficultés à trouver les GPS lors de la première utilisation (« fix »), car sa mémoire est vide, et qu’il ne produit pas de données tant qu’il ne s’est pas synchronisé avec le temps local (RTC) (source). Vu que la plupart de mes tests étaient en intérieur, je ne comprenais pas pourquoi cela ne voulait pas fonctionner, et un proche m’a conseillé de faire le premier « fix » en étant à l’extérieur, les suivants seront plus faciles ensuite.
Du coup, après avoir fait des p’tits tests en extérieur… Ça a fonctionné 🎉.
Détail à considérer : la date et l’heure fournies par le module sont en GMT, il faut donc adapter en fonction de notre créneau horaire effectif.
Faire fonctionner l’écran
L’écran était très facile à faire fonctionner en suivant le petit tutoriel suivant :
A peu de choses près, la seule véritable modification aura été de changer le SCREEN_ADDRESS
en 0x3C
, car pour des raisons obscures, le modèle que je possède ne répond pas à la documentation proposée.
Un petit souci global dans mes fonctions était le scintillement de l’écran, i.e., chaque fois qu’une information était affichée en plus, l’écran clignotait. L’idée, c’est que la bibliothèque utilisée utilise une sorte de buffer, et ainsi il ne faut appeler le display.display()
qu’une seule fois par update, lorsque tout ton écran est configuré correctement.
Par ailleurs, le lien suivant contient des ressources de base facilement adaptables : https://lastminuteengineers.com/oled-display-arduino-tutorial/.
Rendre les informations sexy
J’ai également perdu BEAUCOUP de temps à essayer de faire en sorte d’avoir un texte qui défile, car je voulais avoir la possibilité d’afficher plus d’informations que ce que l’écran pouvait afficher. J’ai donc passé pas mal de temps à trouver une méthode à partir des deux liens suivants :
Le résultat était néanmoins pas très très satisfaisant pour beaucoup d’efforts, j’ai donc décidé de simplement limiter le nombre de caractères à l’écran par ligne à 10.
Quelle structure pour les données ?
Les structures de données sont toujours un point relativement important pour la conception de machintrucs. Si ta structure est correcte, le développement est plus facile par la suite. Évidemment, c’est quelque chose de très évolutif, mais plus c’est fixé, mieux c’est.
Pour rappel, chaque cône aura comme caractéristiques un identifiant unique (pour le repérer dans la grille), une puissance, et un nombre de boucliers. Associés également seront les coordonnées GPS et le temps local. Finalement, il faut que chaque cône possède un code de capture unique, qui évolue avec le temps.
A ces informations « de base », je souhaite également que chaque cône puisse avoir un petit nom personnalisable, et l’équipe qui a capturé le cône. Pourquoi pas un code de skin par la suite. Enfin, il faut que le cône puisse donner son état, et éventuellement des informations supplémentaires sur cet état.
Le tout m’aura donné la structure suivante :
/* Protocone declarations */ typedef enum State { P_Error = -1, P_Init = 0, P_Loading = 1, P_Ok = 2, } State; typedef struct Protocone { String uniqueid; State state; uint8_t last_update[6]; // y, m, d, h, m, s double lon, lat; uint8_t power, shields; String capture_code; String name, team; String debug; } Protocone;
Pour éviter la triche, il faudra faire attention à quel élément puisse modifier quelle valeur. Ainsi, le cône en lui-même ne pourra mettre à jour que ses coordonnées GPS et temporels, ainsi que son état et son identifiant unique. Tout le reste devra être géré par le serveur, afin d’empêcher des modifications en locales.
Il faudra par la suite ajouter un contrôle des données (checksum) pour être sûr qu’il n’y a pas de tentative de modifications inopportunes… (;.
Petit détail : je n’étais absolument pas certain de comment stocker la date et l’heure correctement, je suis donc parti du principe que j’allais stocker sous forme de nombre chaque élément, et improviser derrière. Suggestion bienvenues.
Communiquer avec l’extérieur
On ne change pas un site de tutoriels qui gagne :
L’idée est toute simple, c’est d’insérer tes identifiants, et de tenter de te connecter en boucle, jusqu’à être connecté.
/* Network init */ WiFi.begin(ssid, password); Serial.println("Connecting"); while(WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); if (millis() > TIMEOUT && self.state == P_Loading) { Serial.println("No WiFi…"); self.state = P_Error; self.debug = "Timeout"; break; } } if (WiFi.status() == WL_CONNECTED) { Serial.println(); Serial.println("Connected!"); Serial.print("Local IP: "); Serial.println(WiFi.localIP()); Serial.print("MAC: "); Serial.println(WiFi.macAddress()); }
Là, deux points à explorer. Le premier, faire en sorte de faciliter la connexion à un réseau WiFi, sans devoir hard bricoler du code, l’autre, faire en sorte que le module fasse aussi office de router, pour que l’on puisse s’y connecter pour du debug local.
L’ESP32 possède également bien d’autres technologies à exploiter, notamment un système de « hivemind » entre ESP32 (ESP-NOW ou ESP-MESH), qui serait INCROYABLE à exploiter pour créer des zones de contrôles, mais ce sera à R&D un petit peu.
La suite
Il reste BEAUCOUP de travail à faire rien que pour le prototype :
- Échanger des données
Je souhaite faire en sorte que le petit module puisse échanger des données avec un serveur Python distant via Internet. Pour tester, j’utilise https://gist.github.com/nitaku/10d0662536f37a087e1b et https://randomnerdtutorials.com/esp32-http-get-post-arduino/, mais à terme, ce sera un serveur Django, pour avoir directement une jolie interface. - Alimenter la bête
En gros, vu que le machin est censé être portable, il vaut mieux faire en sorte que ça fonctionne sur batterie. Manifestement, d’après la documentation, il est possible d’alimenter l’ESP32 soit via USB, soit directement avec une source de courant sur les pins 5V xor 3.3V, voir plus (chaque solution étant indépendante).
Néanmoins, je ne suis pas forcément rassuré avec le fait de « jam » du courant directement dans un pin… Je vais donc faire de l’alimentation par USB, malgré les détails à prendre en compte. Je me dis que c’est intéressant d’une part pour facilement réguler, d’autre part car l’utilisation de piles sera plus instinctive, finalement de légèrement décourager les joueur·euse·s de changer le code « on the go ». On m’a recommandé un petit module à pile, et il faut que j’explore un petit peu. - Design de structure pour l’installation dans un cône
A la fin, il faudra faire en sorte que le proto devienne plus qu’un proto, et soit facilement utilisable et exploitable par toustes. Il faudra donc réfléchir à une structure avec les éléments dedans, facile à appliquer à n’importe quel cône, et « hackable » pour les gens qui veulent aller plus loin.
Petites impressions en 3D et bricolages de bois incoming (;. - Webapp correcte pour gérer les cônes
La partie qui va être importante, c’est l’interface de gestion, tant pour les utilisateur·trice·s que pour les admins. Il faut que le jeu soit facilement utilisable sur le terrain, avec peu de contraintes et peu de latence, et adapté aux mobiles comme au ordinateurs.
L’interface d’administration devra aussi être complète, pour faciliter la maintenance et le suivi. - Communiquer avec/gérer les autres cônes
Comme développé un peu plus haut, je suis très curieux de voir comment faciliter la communication en locale avec les différents cônes.
Un truc à explorer, c’est la possibilité de mettre à jour le code des cônes « on the air » en utilisant la fonctionnalité OTA. C’est un truc de DINGUE où tu peux juste envoyer ton code par WiFi à ton ESP32 et ça le met à jour. Woah. - Rendre les choses un peu propre
Il me tient à cœur de correctement documenter le projet, et faire en sorte que ça soit le plus facilement reproductible possible !
J’ai aussi commissionné une amie pour me réaliser un logo et un petit univers graphique autour du projet. Je souhaite que ce soit fortement inspiré de Jet Set Radio ou Lethal League Blaze, du style haut en couleur et pseudo gangsta.
Voilà pour la grosse update. Je pense je vais tenter de faire des articles un peu plus réguliers, modulo le temps disponible.
Stache
Re, GPS : Meilleure antenne ? https://learn.adafruit.com/adafruit-ultimate-gps/external-antenna