Bonjour à tous !
Ce post fait echo au dernier post de Mike sur l'IA : https://www.robot-ma...en-pensez-vous/
L'open source a toujours reposé sur un pacte tout simple : je partage mon code, mais sous une licence qui pose des règles. GPL, MIT, Apache, LGPL… peu importe : tu réutilises, à condition de respecter le contrat (attribution, partage à l'identique, mention de la licence, etc.). C'est ce contrat, et la confiance qui va avec, qui fait tenir tout l'édifice depuis 30 ans.
Sauf que l'IA générative est venue mettre un sacré coup de pied dedans. Et je ne parle pas d'un débat théorique : ça se joue déjà devant les tribunaux.
Les gros modèles de génération de code ont avalé des milliards de lignes publiées sur GitHub et ailleurs, dont énormément de code copyleft. Le modèle « digère » tout ça et te ressort des fonctions… sans licence, sans attribution, sans qu'on sache d'où ça vient.
C'est exactement le cœur de l'affaire Doe v. GitHub, lancée fin 2022 contre GitHub, Microsoft et OpenAI à propos de Copilot. Le juge a écarté les principales accusations de violation pure du droit d'auteur, faute de preuve que Copilot recrachait du code identique ligne pour ligne. Mais, et c'est là que ça devient intéressant pour nous, il a laissé vivre la plainte pour rupture de contrat et violation de licence open source, en acceptant de traiter une licence open source comme un contrat contraignant. Autrement dit : même si ce n'est pas du « copier-coller », ignorer les conditions d'une licence pourrait suffire à se faire condamner. L'affaire est aujourd'hui remontée devant la cour d'appel du 9e circuit, avec des plaidoiries tenues en février 2026. La réponse qui en sortira concerne potentiellement chacun d'entre nous qui publie du code. (l'article dont je parle : https://yanglawoffices.com/github-copilot-open-source-licensing-for-developers-and-startups/)
Deuxième front, plus sournois. Face à l'IA, la définition même d'open source est devenue floue, au point que l'Open Source Initiative a dû publier fin 2024 une « Open Source AI Definition » pour tenter de clarifier. Elle exige notamment un accès réel aux informations sur les données d'entraînement.
Et là, surprise : la plupart des modèles présentés comme « open source » ne passent pas le test. Le cas d'école, c'est Llama de Meta, que tout le monde appelle « open source ». Sauf que sa licence restreint l'usage commercial au-delà d'un certain nombre d'utilisateurs, ne donne pas accès aux données d'entraînement, et impose même des blocages géographiques. On appelle ça de l'open washing : récupérer l'image sympa de l'open source sans en jouer les règles. Un peu comme certenne start du showbuiss qui ont prennent le jet pour faire 200km mais qui font des campagne contre le réchauffement climatique parce que quand meme c'est important la planete et le développement durable... D'où la distinction qui monte partout aujourd'hui entre « open weights » et « open source ». Ce n'est pas la même chose, et l'amalgame arrange bien certains.
Le paradoxe qui me gène vraiment : l'open source, inventé pour rendre le savoir libre et partagé, sert aujourd'hui de matière première gratuite à des modèles souvent fermés et propriétaires. On donne, ils encaissent, et ils ne rendent pas forcément. Le communisme du code au service du capitalisme de l'IA, en quelque sorte...
Je pense qu'il y a aussi une vraie bonne nouvelle. L'IA abaisse énormément la barrière d'entrée : elle aide à comprendre un projet inconnu, à le documenter, à corriger un bug, à contribuer à des dépôts qu'on n'aurait jamais osé toucher. Pour un projet open source qui manque de contributeurs, c'est peut-être une chance autant qu'une menace. Sans compter que l'IA permet à des débutants de se lancer et, à terme, de nourrir à leur tour la communauté. D'ailleurs ! On voit émerger des clauses « no AI training » dans certaines licences, des dépôts qui se ferment, des devs qui quittent carrément GitHub. Est-ce la bonne réponse… ou juste une manière de saborder l'esprit d'ouverture qui a fait la force du libre ?
Il y a pas longtemps j'ai survolé cet article (https://www.termscor...-agency-clients) au début il m'avait semblé intéressant, mais je me pose quand même la question de la valeur juridique réelle de ce type de clause, notamment dans le contexte français ou européen.
Je me demande également comment une telle clause pourrait être concrètement appliquée. Supposons qu'une personne accuse une entreprise d'avoir utilisé son code pour entraîner un LLM : comment peut-elle réellement le démontrer ?
Le problème est que le fonctionnement d'un LLM rend la preuve particulièrement complexe. Une fois le modèle entraîné, le code source n'est évidemment pas stocké sous la même forme dans le modèle : il a contribué à modifier les paramètres du réseau, et on se retrouve avec des milliards de paramètres numériques plutôt qu'avec une copie identifiable du fichier source. Il n'est donc pas forcément possible de faire un simple rapprochement entre le code original et le modèle entraîné.
On peut comparer ça à une pincée de farine dans une pâte à crêpes : une fois mélangée et transformée, il devient extrêmement difficile de démontrer qu'une farine précise provenait de telle ou telle source. La farine a bien contribué au résultat final, mais le résultat ne permet pas nécessairement de remonter jusqu'à la pincée d'origine.
ChatGPT Image 26 août 2026, 16_53_39.png 1,26 Mo
0 téléchargement(s)
Cela pose alors une vraie difficulté probatoire : si l'entreprise ne joue pas le jeu, comment démontrer qu'elle a effectivement utilisé ce code dans son jeu de données d'entraînement ? Elle pourrait simplement nier l'utilisation, et il serait extrêmement difficile pour le freelance d'obtenir la totalité des données ayant servi à entraîner le modèle, notamment s'il s'agit d'un modèle propriétaire.
À mon sens, la question essentielle n'est donc pas seulement « est-ce qu'une clause interdisant l'entraînement d'un modèle est juridiquement valable ? », mais plutôt : « comment cette clause peut-elle être effectivement opposée et prouvée en cas de litige ? »
C'est là que je trouve que l'article est un peu léger : il explique assez bien comment interdire contractuellement l'utilisation des données, mais beaucoup moins comment établir la violation de cette interdiction lorsqu'on n'a pas accès au pipeline d'entraînement, aux datasets ou aux logs internes de l'entreprise.
Et finalement, c'est peut-être là que se trouve le vrai problème : une interdiction peut être parfaitement écrite sur le papier, mais si personne n'est capable de démontrer qu'elle a été violée, quelle est réellement son efficacité ?
Curieux d'avoir vos avis, notamment si certains ici ont des connaissances en droit, en propriété intellectuelle, en IA ou ont déjà été confrontés à ce genre de situation.
Cette vidéo est un peu moins directement liée au sujet, mais je la trouve intéressante car elle permet de bien synthétiser le cadre juridique européen autour de l’IA, et notamment les différentes obligations qui commencent à s’appliquer aux acteurs développant ou utilisant ces systèmes.
Et vous, qu'en pensez-vous ?
Vous continuez à publier vos projets (code, STEP, schémas KiCad…) sans arrière-pensée, ou vous commencez à faire attention à ce que vous exposez ?
Une licence open source a-t-elle encore un sens si personne ne peut vérifier ce qui entre dans un modèle ?
On va vers un open source « à la carte », avec des clauses anti-entraînement, et est-ce que ça reste encore de l'open source ?
Et pour les makers et roboticiens ici : ça change quoi concrètement à votre manière de partager vos projets ?
- Robot Maker
- → Affichage d'un profil : Sujets: Furyoisivie
Furyoisivie
Inscrit(e) (le) 13 janv. 2026Déconnecté Dernière activité sept. 02 2026 01:02




À propos de moi
Étudiant ingénieur à l’ESTIA et passionné par tout ce qui touche à la robotique, l’électronique, l’informatique et l’IA. Je travaille en alternance chez Robot-Maker, ce qui me permet de transformer pas mal de mes idées et expérimentations en projets concrets.
Je m’intéresse particulièrement aux robots mobiles, à Vigibot, au SLAM, aux systèmes embarqués, aux Raspberry Pi, à l’électronique et au développement logiciel. Je suis un grand pationné de l'IA et des opportunité qu'elle donne ! Je passe aussi pas mal de temps à expérimenter avec différents outils et technologies, parfois avec un résultat parfaitement fonctionnel… et parfois avec un composant qui finit mystérieusement par fumer..
J’aime surtout comprendre comment les choses fonctionnent, démonter, expérimenter, bricoler et partager ce que j’apprends. Je suis donc autant intéressé par une discussion technique approfondie que par un projet un peu expérimental réalisé « juste pour voir si ça marche ».
Au plaisir d’échanger avec vous sur le forum ! ![]()
Statistiques de la communauté
- Groupe Membres
- Messages 12
- Visites sur le profil 635
- Titre Nouveau membre
- Âge 24 ans
- Date de naissance Juin 18, 2002
-
Gender
Homme
-
Location
Bayonne
-
Interests
Robotique
Fabrication additive
Intelligence artificielle
Usinage
Sujets que j'ai initiés
L'IA menace t'il l'open source ?
26 août 2026 - 04:13
Horloge météo connectée sur dalle LED 64×32 avec le MatrixPortal S3
21 août 2026 - 03:15
Salut à tous ! ![]()
Je partage un petit projet perso que je viens de finir : un afficheur qui alterne entre une horloge (heure, date, barre de progression des secondes) et une page météo avec des icônes animées soleil dont les rayons tournent, gouttes qui tombent, flocons, éclair d'orage… le tout sur un panneau LED matriciel.
Les données de température et de conditions viennent de l'API Open-Meteo (gratuite, sans clé), et l'heure est synchronisée par NTP. Avantage pas besoin de RTC !
Comment ça marche ?
L'heure, sans horloge. Au démarrage, la carte se connecte au WiFi puis synchronise l'heure par NTP. Une seule ligne gère le fuseau français et le passage heure d'été / heure d'hiver automatiquement :
configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "pool.ntp.org", "time.nist.gov");
La météo, gratuitement. C'est là qu'intervient Open-Meteo. C'est une API météo open-source, gratuite pour un usage non commercial (maximum de 10 000 appels API par jours) et sans clé API : pas de compte, pas d'inscription simplement y faire référence en précisant qu'il s'agit d'une licence CC BY 4.0, on tape une URL et on reçoit du JSON. Elle s'appuie notamment sur les modèles de Météo-France (Arome / Arpège), ce qui tombe bien chez nous.
On lui envoie des coordonnées GPS et on récupère la température + un weathercode (codes WMO standard), qu'on range ensuite dans une catégorie d'icône.
Le matériel :
- Un panneau LED HUB75 64×32
- Une carte Adafruit Matrix Portal S3 (ESP32) pour piloter le tout le WiFi intégré est parfait pour aller chercher l'heure et la météo
- Une alimentation 5 V de 4A (consommation max du panneau)
Le fonctionnement
Côté logiciel, ça reste assez simple :
- Au démarrage : connexion WiFi synchro NTP (avec le fuseau France et le passage heure d'été/hiver automatique) → première requête météo.
- Ensuite le programme alterne deux pages à intervalle réglable : ~6 s d'horloge, ~5 s de météo.
- La météo se rafraîchit toutes les 15 min en tâche de fond.
- Les icônes sont dessinées à la main (cercles, lignes, rectangles) et animées via un compteur de « phase » incrémenté à 15 fps → c'est ce qui fait tourner les rayons du soleil et descendre les gouttes.
- Les codes météo renvoyés par Open-Meteo sont regroupés en 7 catégories (soleil, éclaircies, nuageux, brouillard, pluie, neige, orage) pour choisir l'icône et le libellé à afficher.
Côté bibliothèques : le cœur ESP32 (WiFi / HTTPClient / WiFiClientSecure), ArduinoJson v7 pour parser la réponse de l'API, `time.h` pour le NTP, et une lib de pilotage du panneau HUB75.
1000020277.jpg 163,02 Ko
0 téléchargement(s)
1000020276.jpg 157,74 Ko
0 téléchargement(s)
Deux ou trois pièges rencontrés...
- Mise en page : sur 64 px de large, il faut vraiment réfléchir à la disposition. J'ai fini avec l'icône et la température symétriques de part et d'autre du centre, et le libellé centré en dessous comme une légende.
- Couleurs inversées : mon jaune sortait… violet ! C'est la signature classique d'une inversion des canaux vert/bleu du panneau : le jaune (255, 205, 0) devient magenta (255, 0, 205), alors que le blanc reste blanc (d'où le fait qu'on ne le voit pas tout de suite). À vérifier selon le panneau et la lib utilisés.
- Pour valider le rendu des icônes sans attendre la vraie météo, j'ai ajouté un petit mode test qui utilise les boutons UP/DOWN de la Matrix Portal pour faire défiler les 7 catégories à la main.
Le code :
J'ai utilisé Claude pour faire un Wrapper de Protomatter pour simplifier la configuration du ou des panneaux. Je vous mets la librarie dispo sur le Github de Robot-Maker attention elle est valable uniquement pour le matrix portal S3 (PIN fixés dans la librarie) : https://github.com/R...rie-Hub75Screen
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h> // à installer via le gestionnaire de bibliothèques (v7)
#include <time.h>
#include <math.h>
#include <Hub75Screen.h>
//=================== TEST ICONE =================
//#define TEST_ICONS //à décommenter pour tester les icones
// ================== CONFIG À REMPLIR ==================
#define WIFI_SSID "NOM_WIFI"
#define WIFI_PASS "MOT_DE_PASSE"
// Coordonnées Géographique
#define LAT "43.49"
#define LON "-1.48"
#define TZ_FRANCE "CET-1CEST,M3.5.0,M10.5.0/3"
// =====================================================
Hub75Screen screen(64, 32, 1, Hub75Screen::HORIZONTAL, 4, true);
const uint8_t Brightness = 100;
const uint32_t PAGE_MS[2] = {6000, 5000};
const char *jours[] = {"DIM","LUN","MAR","MER","JEU","VEN","SAM"};
const char *mois[] = {"JAN","FEV","MAR","AVR","MAI","JUIN",
"JUIL","AOUT","SEP","OCT","NOV","DEC"};
enum WxCat { WX_CLEAR, WX_PARTLY, WX_CLOUD, WX_FOG, WX_RAIN, WX_SNOW, WX_STORM };
bool wxValid = false;
int wxTemp = 0;
WxCat wxCat = WX_CLOUD;
WxCat wxCategory(int code) {
if (code == 0) return WX_CLEAR;
if (code == 1 || code == 2) return WX_PARTLY;
if (code == 3) return WX_CLOUD;
if (code == 45 || code == 48) return WX_FOG;
if (code >= 71 && code <= 77) return WX_SNOW;
if (code == 85 || code == 86) return WX_SNOW;
if (code >= 95) return WX_STORM;
return WX_RAIN;
}
const char *wxLabel(WxCat c) {
switch (c) {
case WX_CLEAR: return "SOLEIL";
case WX_PARTLY: return "COUVERT";
case WX_CLOUD: return "NUAGEUX";
case WX_FOG: return "BROUILLARD";
case WX_RAIN: return "PLUIE";
case WX_SNOW: return "NEIGE";
case WX_STORM: return "ORAGE";
}
return "";
}
-
void printCentered(const char *s, int y, uint8_t size, uint16_t col) {
int w = (int)strlen(s) * 6 * size;
screen.setTextSize(size);
screen.setTextColor(col);
screen.setCursor((screen.width() - w) / 2, y);
screen.print(s);
}
void boot(const char *msg) {
screen.clear();
printCentered(msg, 12, 1, screen.color(255, 255, 255)); // Texte de boot en BLANC
screen.update();
}
void drawTempSmall(int t, int x, int y, uint16_t col) {
char num[6];
snprintf(num, sizeof(num), "%d", t);
int nw = (int)strlen(num) * 6;
screen.setTextSize(1);
screen.setTextColor(col);
screen.setCursor(x, y); screen.print(num);
screen.drawCircle(x + nw + 1, y + 1, 1, col); // le petit "°"
screen.setCursor(x + nw + 4, y); screen.print("C");
}
// =================== ICÔNES MÉTÉO ANIMÉES (version compacte) ===================
void drawSun(int cx, int cy, int r, int phase) {
uint16_t jaune = screen.color(255, 0, 200);
uint16_t clair = screen.color(255, 240, 150);
for (int a = 0; a < 360; a += 45) { // 8 rayons au lieu de 12
float rad = (a + phase * 2) * DEG_TO_RAD;
screen.drawLine(cx + cos(rad) * (r + 2), cy + sin(rad) * (r + 2),
cx + cos(rad) * (r + 4), cy + sin(rad) * (r + 4), jaune);
}
screen.fillCircle(cx, cy, r, jaune);
screen.fillCircle(cx - 1, cy - 1, r / 3, clair);
}
void drawNiceCloud(int cx, int cy) {
uint16_t body = screen.color(255, 255, 255);
screen.fillCircle(cx - 4, cy + 1, 3, body);
screen.fillCircle(cx + 4, cy + 1, 3, body);
screen.fillCircle(cx - 1, cy - 2, 4, body);
screen.fillCircle(cx + 2, cy, 3, body);
screen.fillRect(cx - 6, cy + 1, 12, 3, body);
}
void drawRain(int cx, int cyCloud, int phase) {
uint16_t rain = screen.color(60, 130, 255);
const int cols[] = {-4, -1, 2, 5};
const int span = 6;
for (int i = 0; i < 4; i++) {
int y = (phase * 2 + i * 5) % span;
int top = cyCloud + 6 + y;
screen.drawLine(cx + cols[i], top, cx + cols[i], top + 2, rain);
}
}
void drawBolt(int cx, int cy) {
uint16_t bolt = screen.color(255, 0, 235);
screen.drawLine(cx + 1, cy, cx - 2, cy + 4, bolt);
screen.drawLine(cx - 2, cy + 4, cx + 1, cy + 4, bolt);
screen.drawLine(cx + 1, cy + 4, cx - 2, cy + 9, bolt);
}
void drawWeatherIcon(WxCat c, int cx, int cy, int phase) {
switch (c) {
case WX_CLEAR:
drawSun(cx, cy, 4, phase);
break;
case WX_PARTLY:
drawSun(cx - 4, cy - 4, 3, phase);
drawNiceCloud(cx + 2, cy + 3);
break;
case WX_CLOUD:
drawNiceCloud(cx, cy + (int)lround(sin(phase * 0.15) * 1.5));
break;
case WX_FOG:
drawNiceCloud(cx, cy - 2);
for (int i = 0; i < 3; i++)
screen.drawLine(cx - 6, cy + 5 + i * 2, cx + 6, cy + 5 + i * 2, screen.color(120,120,135));
break;
case WX_RAIN:
drawNiceCloud(cx, cy - 2);
drawRain(cx, cy - 2, phase);
break;
case WX_SNOW:
drawNiceCloud(cx, cy - 2);
for (int i = 0; i < 4; i++) {
int y = (phase + i * 4) % 7;
screen.fillCircle(cx - 4 + i * 3, cy + 4 + y, 1, screen.color(220, 230, 255));
}
break;
case WX_STORM:
drawNiceCloud(cx, cy - 2);
drawRain(cx, cy - 2, phase);
if ((phase % 45) < 5) drawBolt(cx, cy + 1);
break;
}
}
// ---------- Météo (Open-Meteo) ----------
void fetchWeather() {
if (WiFi.status() != WL_CONNECTED) return;
WiFiClientSecure client;
client.setInsecure();
HTTPClient https;
String url = String("https://api.open-meteo.com/v1/forecast?latitude=")
+ LAT + "&longitude=" + LON + "¤t_weather=true";
if (https.begin(client, url)) {
if (https.GET() == 200) {
JsonDocument doc;
if (deserializeJson(doc, https.getString()) == DeserializationError::Ok) {
float temp = doc["current_weather"]["temperature"] | NAN;
int wc = doc["current_weather"]["weathercode"] | -1;
if (!isnan(temp) && wc >= 0) {
wxTemp = (int)lround(temp);
wxCat = wxCategory(wc);
wxValid = true;
}
}
}
https.end();
}
}
// ---------- Rendu : PAGE HORLOGE ----------
void renderClock(const struct tm &t) {
// Heure HH:MM en taille 2, centrée en BLANC
char hhmm[6];
snprintf(hhmm, sizeof(hhmm), "%02d:%02d", t.tm_hour, t.tm_min);
printCentered(hhmm, 2, 2, screen.color(255, 255, 255));
// Barre des secondes (barre de progression en blanc)
int barW = map(t.tm_sec, 0, 59, 0, 58);
screen.drawRect(2, 19, 60, 3, screen.color(40, 40, 60));
screen.fillRect(3, 20, barW, 1, screen.color(255, 255, 255));
// Date au format JJ/MM/AAAA en BLANC
char d[16];
snprintf(d, sizeof(d), "%02d/%02d/%04d", t.tm_mday, t.tm_mon + 1, t.tm_year + 1900);
printCentered(d, 23, 1, screen.color(255, 255, 255));
}
// ---------- Rendu : PAGE MÉTÉO ----------
void renderWeather(int phase) {
if (!wxValid) {
printCentered("METEO ?", 12, 1, screen.color(255, 255, 255));
return;
}
uint16_t white = screen.color(255, 255, 255);
const int midY = 9;
drawWeatherIcon(wxCat, 16, midY, phase);
char num[6];
snprintf(num, sizeof(num), "%d", wxTemp);
int len = strlen(num);
uint8_t ts = (len <= 2) ? 2 : 1;
int digitsW = len * 6 * ts;
int degR = (ts == 2) ? 2 : 1;
int blockW = digitsW + degR + 3;
int x = 48 - blockW / 2;
int y = midY - (7 * ts) / 2;
screen.setTextSize(ts);
screen.setTextColor(white);
screen.setCursor(x, y);
screen.print(num);
screen.drawCircle(x + digitsW + degR, y + degR, degR, white);
screen.setTextSize(1);
screen.setTextColor(white);
const char *lbl = wxLabel(wxCat);
int lw = strlen(lbl) * 6;
screen.setCursor((64 - lw) / 2, 24);
screen.print(lbl);
}
// ---------- Aiguillage des pages ----------
void render(int page, int phase) {
struct tm t;
if (!getLocalTime(&t)) { boot("SYNC..."); return; }
screen.clear();
if (page == 0) renderClock(t);
else renderWeather(phase);
screen.update();
}
// ---------- Setup / Loop ----------
uint32_t lastWx = 0;
uint32_t pageStart = 0;
int page = 0;
void setup() {
Serial.begin(115200);
if (!screen.begin()) { for (;;) delay(100); }
screen.setBrightness(Brightness);
#ifdef TEST_ICONS
testIconsSetup();
return;
#endif
boot("WIFI...");
WiFi.begin(WIFI_SSID, WIFI_PASS);
uint32_t t0 = millis();
while (WiFi.status() != WL_CONNECTED && millis() - t0 < 20000) delay(250);
if (WiFi.status() == WL_CONNECTED) {
boot("NTP...");
configTzTime(TZ_FRANCE, "pool.ntp.org", "time.nist.gov");
fetchWeather();
lastWx = millis();
} else {
boot("PAS DE WIFI");
delay(1500);
}
pageStart = millis();
}
void loop() {
#ifdef TEST_ICONS
testIconsLoop();
return;
#endif
static int phase = 0;
uint32_t now = millis();
if (now - lastWx > 15UL * 60UL * 1000UL) {
fetchWeather();
lastWx = now;
}
if (now - pageStart > PAGE_MS[page]) {
page = (page + 1) % 2;
pageStart = now;
}
if (screen.tick(15)) {
render(page, phase);
phase++;
}
}
// =================== MODE TEST : DISPOSITION DES ICÔNES ===================
#if defined(BUTTON_UP) && defined(BUTTON_DOWN)
#define BTN_UP BUTTON_UP // macros du Matrix Portal si le core les définit
#define BTN_DOWN BUTTON_DOWN
#else
#define BTN_UP 6 // Matrix Portal S3 : UP=6 / DOWN=7
#define BTN_DOWN 7 // Matrix Portal M4 : UP=2 / DOWN=3
#endif
const char *wxCatName[] = {"CLEAR","PARTLY","CLOUD","FOG","RAIN","SNOW","STORM"};
void testIconsSetup() {
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
wxValid = true;
wxTemp = 23; // température factice pour juger la mise en page
Serial.println("== MODE TEST ICONES ==");
}
void testIconsLoop() {
static int cat = 0;
static int phase = 0;
static bool autoCycle = false; // défilement auto (activé par UP)
static bool upPrev = HIGH, downPrev = HIGH;
static uint32_t lastEdge = 0; // horodatage du dernier appui pris en compte
static uint32_t lastStep = 0; // dernier changement d'icône en auto
const uint32_t DEBOUNCE = 150; // ms anti-rebond
const uint32_t STEP_MS = 1000; // 1 icône par seconde
uint32_t now = millis();
bool up = digitalRead(BTN_UP);
bool down = digitalRead(BTN_DOWN);
if (now - lastEdge > DEBOUNCE) {
if (upPrev == HIGH && up == LOW) {
autoCycle = !autoCycle;
lastStep = now;
lastEdge = now;
Serial.println(autoCycle ? "AUTO ON" : "AUTO OFF");
}
else if (downPrev == HIGH && down == LOW) {
autoCycle = false;
cat = (cat + 6) % 7;
lastEdge = now;
Serial.println(wxCatName[cat]);
}
}
upPrev = up;
downPrev = down;
if (autoCycle && now - lastStep >= STEP_MS) {
cat = (cat + 1) % 7;
lastStep = now;
Serial.println(wxCatName[cat]);
}
wxCat = (WxCat)cat;
if (screen.tick(15)) {
screen.clear();
renderWeather(phase);
screen.update();
phase++;
}
}
La suite
Ça tourne bien ! Quelques pistes en tête : afficher la prévision du lendemain, régler la luminosité automatiquement selon l'heure, ou ajouter une 3ᵉ page (API spotify, Mail, ect...).
Evenemment Robotics Dream Keeper Challenge !
19 mai 2026 - 04:19
Salut à tous !
Un challenge est lancé ! Robotics Dream Keeper Challenge, organisé par D-Robotics autour de leur kit de développement que nous avons en boutique la RDK X5.
Event_RDK.png 689,03 Ko
5 téléchargement(s)
Le concept
Contrairement à un hackathon classique, ce n'est pas une compétition entre participants. C'est un parcours communautaire structuré, pensé pour faire passer un développeur du statut de débutant complet à celui de dev RDK X5 autonome. Quatre paliers : Explorer → Builder → Creator → Core Developer.
Le challenge est découpé en 3 étapes progressives :
- Stage 1 : Ignite Challenge (5-10 jours) : prise en main de la board, premier démo IA qui tourne.
- Stage 2 : Build Challenge (10-15 jours) : conception de votre propre système robotique (archi IA, plan projet).
- Stage 3 : Launch Challenge (20 jours) : projet complet fonctionnel avec inférence IA temps réel accélérée par le BPU du RDK X5.
Guidelines détaillées sur leur GitHub : https://github.com/D...ge/tree/develop
Le support fourni
- Bootcamp en ligne gratuit
- Webinars hebdomadaires
- Sessions 1-on-1 avec des mentors
- Code open-source et templates d'algos optimisés pour le RDK X5
- Communauté Discord active
Les récompenses
- Grand prix : 1 000 $ pour le projet RDK X5 le plus abouti
- TOP Voice Award : 500 $ pour les 3 meilleurs contributeurs communautaires (titre "RDK Advocator")
- Cashback sur l'achat d'une RDK X5 si vous validez les 3 stages
- Badges digitaux, rôles Discord, accès prioritaire aux futurs events D-Robotics
- Tirage au sort merchandising à l'inscription
- Pour les meilleurs : opportunités de collaboration avec l'équipe D-Robotics, conférence dev annuelle, et possibilité de visiter le Robot Innovation Center à Shenzhen
Pour participer
Trois étapes d'inscription obligatoires :
- Rejoindre le serveur Discord D-Robotics : https://discord.gg/ydVxBpz3vP
- Remplir le formulaire d'application : https://forms.gle/ojG5pRmWXMsM27Vb9
- Créer un compte RDK Studio : https://sso.d-robotics.cc/
Source officielle : https://en.d-robotic...am-into-reality
Pour ceux qui veulent se procurer une RDK X5 pour participer, on est là pour répondre à vos questions techniques n'hésitez pas à poser des question sur le forum.
Si les produits RDK vous intéressent, n’hésitez pas à consulter ce lien vers la page des produits RDK disponibles dans la boutique : https://www.robot-ma...op/78-carte_rdk
Pour commencer voici un lien vers un tuto d'installation de l'OS de RDK par Ximun
Bon challenge à tous, et hâte de voir vos projets sur le forum ! ![]()
- Robot Maker
- → Affichage d'un profil : Sujets: Furyoisivie
- Privacy Policy
Mon contenu