loader

I2M.2026.M5Stack. Niveau à bulle accelérométrique (Test de Vibe coding avec Gemini)

Compte rendu d'un test de l'utilisation de Gemini pour faire du Vibe Coding avec un M5Stack

Matériel :
M5stack Fire v2.7

Logiciels :
IDE Arduino 1.8.19

Bibliothèques :
M5Unified.h (En remplacement de M5Stack.h - échange suggéré par Gemini)

PROMPT INTIAL - GEMINI (Google) :
Proposes moi un programme pour M5stack Fire dev 2.7 :
- Mesurer les accélérations selon x, y, z
- Afficher en continu les valeurs à l'écran

BILAN :
- Quelques erreurs rencontrées sur l'utilisation de l'IDE Arduino. Chaque erreur est inscrite comme prompt seul ; Gemini "comprend" qu'il s'agit d'une erreur et propose les modifications. En général ça fonctionne. Au besoin on demande des précisions.
- Le problème principal rencontré est un problème de compatibilité de bibliothèque.
- La compilation des programmes pour M5Stack avec l'IDE Arduino est généralement très long. Une demande à Gemini sur la raison du problème pointe sur la lourdeur des programmes à téléverser, même si ils semblent petits en raison du faible nombre de lignes. Problème de fréquence de communication également pointée.

TRACAS :
- La compilation des programmes pour M5Stack avec l'IDE Arduino est généralement VRAIMENT très long. Beaucoup de temps d'attente avec cette plateforme.

//#include
#include
// Variables pour stocker les valeurs d'accélération
float accX = 0.0F;
float accY = 0.0F;
float accZ = 0.0F;
void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);
  M5.Imu.init(); // Correction ici : minuscule à init
  
  // Configuration initiale de l'écran
  M5.Display.fillScreen(BLACK);
  M5.Display.setTextSize(3);
  M5.Display.setTextColor(CYAN);
  M5.Display.setCursor(40, 10);
  M5.Display.println("ACCELEROMETRE");
  
  // Lignes de séparation pour la lisibilité
  M5.Display.drawFastHLine(0, 45, 320, WHITE);
}
void loop() {
  // 1. Lecture des données du capteur
  M5.update();
  M5.Imu.getAccelData(&accX, &accY, &accZ);
  // 2. Affichage des valeurs à l'écran
  // Note : On définit une couleur de fond (BLACK) dans printf pour éviter le scintillement
  M5.Display.setTextSize(4);
  
  M5.Display.setCursor(20, 70);
  M5.Display.setTextColor(RED, BLACK);
  M5.Display.printf("X: %5.2f G", accX);
  M5.Display.setCursor(20, 120);
  M5.Display.setTextColor(GREEN, BLACK);
  M5.Display.printf("Y: %5.2f G", accY);
  M5.Display.setCursor(20, 170);
  M5.Display.setTextColor(BLUE, BLACK);
  M5.Display.printf("Z: %5.2f G", accZ);
  // Petite pause pour stabiliser l'affichage
  delay(100);
}

M5Stack Valeurs accélération

PROMPT n°1 - GEMINI (Google) :
Je veux désormais modifier le programme pour réaliser un niveau à bulle.
- Il doit y avoir un visuel type niveau à bulle a deux dimensions
- L'écran est positionné vers le haut
- Il doit pouvoir être mis à zéro en appuyant sur un bouton
- Il doit indiquer le décalage en ° par rapport au zéro selon X et selon Y en bas de l'écran

BILAN n°1 :
- Le programme fonctionne du 1er coup.
- Deux problèmes identifiés :
=> Les pixels en dehors du cercle blanc restent rouges si ils sont atteints par la "bulle" rouge
=> Beaucoup d'incertitudes de mesures impliquent une bulle qui tremblotte beaucoup

PROMPT n°2 - GEMINI (Google) :
Ajuster le programme:
- le point rouge en dehors de la zone blanche doit être effacé, pour l'instant il reste affiché
- Faire des mesures et se baser sur une moyenne des 10 dernières mesures
- Garder les corrections de bibliothèques précédentes

BILAN n°2 :
- Le prompt de demande de modification n'est pas très précis concernant les pixels qui restent rouges
- Malgré ça la proposition proposée fonctionne du premier coup
 => Il n'y a plus de pixels qui restent rouges en dehors du cercle blanc
 => La bulle est beaucoup plus stable mais tremblotte encore un petit peu
- Un problème supplémentaire non identifié précédemment :
 => La bulle se déplace du mauvais côté


PROMPT n°3 - GEMINI (Google) :
la bulle se déplace du mauvais côté. A quel endroit du code puis je le modifier moi même ?

Bilan n°3 :
- Gemini a un bon retour analytique sur les programmes qu'il propose
- Le programme est entièrement fonctionnel en moins d'une heure.

#include
#include
// Variables pour le calibrage (mise à zéro)
float offsetX = 0.0, offsetY = 0.0;
float angleX = 0.0, angleY = 0.0;
void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);
  M5.Imu.init();
  
  M5.Display.setRotation(1); // Orientation standard
  M5.Display.fillScreen(BLACK);
}
void loop() {
  M5.update();
  
  // 1. Lecture de l'accéléromètre
  float ax, ay, az;
  M5.Imu.getAccelData(&ax, &ay, &az);
  // 2. Calcul des angles en degrés (inclinaison par rapport à la verticale Z)
  // On utilise atan2 pour convertir les forces G en degrés
  float currentAngleX = atan2(ax, az) * 180.0 / M_PI;
  float currentAngleY = atan2(ay, az) * 180.0 / M_PI;
  // 3. Mise à zéro (Calibrage) si on appuie sur le bouton central (BtnB)
  if (M5.BtnB.wasPressed()) {
    offsetX = currentAngleX;
    offsetY = currentAngleY;
    M5.Speaker.tone(1000, 100); // Petit bip de confirmation
  }
  // Calcul de l'angle relatif
  angleX = currentAngleX - offsetX;
  angleY = currentAngleY - offsetY;
  // 4. Dessin du niveau à bulle
  M5.Display.startWrite(); // Accélère l'affichage
  
  // Effacer la zone de la bulle (cercle noir)
  M5.Display.fillCircle(160, 100, 80, BLACK);
  M5.Display.drawCircle(160, 100, 80, WHITE); // Contour du niveau
  M5.Display.drawCircle(160, 100, 10, WHITE); // Cible centrale
  // Calcul de la position de la bulle (sensibilité x5 pour le visuel)
  int bubbleX = 160 - (angleX * 5);
  int bubbleY = 100 + (angleY * 5);
  // Contraindre la bulle à rester dans le cercle
  bubbleX = constrain(bubbleX, 85, 235);
  bubbleY = constrain(bubbleY, 25, 175);
  // Dessin de la bulle (Verte si proche de zéro, rouge sinon)
  uint16_t color = (abs(angleX) < 0.5 && abs(angleY) < 0.5) ? GREEN : RED;
  M5.Display.fillCircle(bubbleX, bubbleY, 15, color);
  // 5. Affichage des valeurs numériques en bas
  M5.Display.setCursor(20, 200);
  M5.Display.setTextColor(WHITE, BLACK);
  M5.Display.setTextSize(2);
  M5.Display.printf("X: %5.1f deg  |  Y: %5.1f deg", angleX, angleY);
  
  M5.Display.setCursor(60, 225);
  M5.Display.setTextSize(1);
  M5.Display.print("Appuyez sur Bouton B pour Tarer (Zero)");
  M5.Display.endWrite();
  
  delay(20); // Fluide (50 images par seconde)
}

#include
#include
// Paramètres de lissage (moyenne glissante sur 10 mesures)
const int nbMesures = 10;
float mesuresX[nbMesures], mesuresY[nbMesures];
int indexMesure = 0;
// Variables de calibrage et positions
float offsetX = 0.0, offsetY = 0.0;
int lastBubbleX = 160, lastBubbleY = 100; // Pour effacer proprement
void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);
  M5.Imu.init(); // "init" en minuscule pour M5Unified
  
  M5.Display.setRotation(1);
  M5.Display.fillScreen(BLACK);
  
  // Initialisation des tableaux à zéro
  for(int i=0; i

#include
#include
// Paramètres de lissage (moyenne glissante sur 10 mesures)
const int nbMesures = 10;
float mesuresX[nbMesures], mesuresY[nbMesures];
int indexMesure = 0;
// Variables de calibrage et positions
float offsetX = 0.0, offsetY = 0.0;
int lastBubbleX = 160, lastBubbleY = 100; // Pour effacer proprement
void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);
  M5.Imu.init(); // "init" en minuscule pour M5Unified
  
  M5.Display.setRotation(1);
  M5.Display.fillScreen(BLACK);
  
  // Initialisation des tableaux à zéro
  for(int i=0; i

Niveau à bulle 2D