///////////////////////// // POCL Poke // ///////////////////////// /* * Un POCL imaginé et réalisé au Hackathon POCL à l'édulab Rennes 2 les 9 et 10 décembre 2021. * * Difficultés : * Configurez le logiciel Arduino pour gérer la carte D1 mini (ESP8266). * Intégrer les biobliothèues requises par le projet : ** #include -> pour gérer le protocole de communication, c'est la bibliothèque MQTT de Joël Gähwiler : https://github.com/256dpi/arduino-mqtt ** #include -> pour gérer les rubans de led ** #include -> Bibliothèque WiFiManager pour configurer automatiquement le réseau wifi et le mot de passe. * * BROCHAGE _________________ / D1 mini \ - |[ ]RST TX[ ]| - - |[ ]A0 -GPIO RX[ ]| - |[ ]D0-16 5-D1[ ]| - |[ ]D5-14 4-D2[ ]| - Bouton - |[X]D6-12 0-D3[X]| - ruban de leds - |[ ]D7-13 2-D4[ ]| LED_BUILTIN - |[ ]D8-15 GND[X]| - GND (Boutons, ruban de leds) - |[ ]3V3 . 5V[X]| - ruban de Led | +---+ | |_______|USB|_______| Matériel : - des fils dupont. - un ruban de led RGB WS28B12 - D1 mini (Wemos, LOLIN,...) - bouton poussoir - une alimentation 5V */ /* * Un travail d'équipe de : * Alma Oskouei * Gaëlle Bescond * Tony Vanpoucke * Wing-Anh Luy * Antony Le Goïc-Auffret ___ / ___ \ |_| | | /_/ _ ___ _ |_| |___|_| |_ ___|_ _| |___| |_| Les petits Débrouillards - juillet 2022 CC-By-Sa http://creativecommons.org/licenses/by-nc-sa/3.0/ // Programme nourri de https://randomnerdtutorials.com/esp32-esp8266-rgb-led-strip-web-server/ // Programme inspiré de celui par Joël Gähwiler // https://github.com/256dpi/arduino-mqtt Améliorations : reboot en cas de déconnexion MQTT */ #include #include // Bibliothèque MQTT par Joël Gaehwiler #include // Bibliothèque NeoPixel d'Adafruit #include // Bibliothèque WiFiManager pour configurer automatiquement le réseau wifi et le mot de passe. #include WiFiClient net; //on crée l'objet WiFiClient "Net" WiFiServer serveurPOCL(80); MQTTClient clientMQTT; #define BROKER_IP "debrouillards.ddns.net" //IP du serveur sur lequel est installé le Broker MQTT unsigned long lastMillis = 0; char nomPOCL[25]; // variable de stockage du nom unique du POCL //=============Eléments pour le ruban de led et le bouton=============== // Broche de connexion du ruban de LED #define PIN D3 // int brocheBouton = 12; //GPIO de la broche D6 int rouge = 34; int bleu = 10; int vert = 255; // Nombre de Led RDGB dans votre ruban #define NUMPIXELS 8 // on configurer un ruban nommé "pixels" Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); #define T 1 // temps pour gérer le fade du ruban //============================================================== //===============Eléments pour le choix de la couleur du Ruban=============== // Pour décoder les valeurs de HTTP GET String redString = "0"; String greenString = "0"; String blueString = "0"; int pos1 = 0; int pos2 = 0; int pos3 = 0; int pos4 = 0; // Variable to store the HTTP req uest String header; // Setting PWM bit resolution // const int resolution = 256; // Current time unsigned long currentTime = millis(); // Previous time unsigned long previousTime = 0; // Define timeout time in milliseconds (example: 2000ms = 2s) const long timeoutTime = 2000; //============================================================================== void connect() { Serial.print("Vérification de la connexion Wifi..."); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(1000); } Serial.println("\nPOCL Connecté au Wifi :-) "); Serial.print("\nconnexion au serveur MQTT en cours "); //connection au serveur MQTT : identifiant, User, mot de passe while (!clientMQTT.connect(nomPOCL, "poclpokou", "pokou")) { Serial.println("."); delay(300); } Serial.println("\nconnecté à MQTT !"); // on s'abonne au sujet (topic) "/Poke" clientMQTT.subscribe("/Poke"); // Attention à la casse !! La casse c'est maj ou minuscule Serial.println("Abonné à /Poke"); } void messageReceived(String &topic, String &payload) { digitalWrite(LED_BUILTIN, HIGH); fade(); Serial.println("incoming: " + topic + " - " + payload); if (payload == "pokou"){ Serial.println("clic !"); digitalWrite(LED_BUILTIN, LOW); delay(100); digitalWrite(LED_BUILTIN, HIGH); } } void fade() { EEPROM.get(0, rouge); Serial.print("Valeur de rouge EEPROM = "); Serial.println(rouge); EEPROM.get(4, vert); Serial.print("Valeur de vert EEPROM = "); Serial.println(vert); EEPROM.get(8, bleu); Serial.print("Valeur de bleu EEPROM = "); Serial.println(bleu); for (int sig=0; sig<3; sig++){ for (int b=0; b<255; b++){ pixels.setBrightness(b); for(int i=0; i1; b--){ //boucle de gestion de la brillance pixels.setBrightness(b); // n'oubliez pas que le premier pixel porte le Numéro 0 for(int i=0; i=0) { // Si il y en a on ne fait rien Serial.println("Il y a des infos dans la mémoire"); Serial.print(EEPROM.percentUsed()); Serial.println("% de l'espace mémoire flash de l'ESP flash actuellement utilisé."); EEPROM.get(0, rouge); Serial.print("Valeur de rouge EEPROM = "); Serial.println(rouge); EEPROM.get(4, vert); Serial.print("Valeur de vert EEPROM = "); Serial.println(vert); EEPROM.get(8, bleu); Serial.print("Valeur de bleu EEPROM = "); Serial.println(bleu); } else { // Si il n'y en a pas on stocke la couleur pas défaut EEPROM.put(0, rouge); EEPROM.put(4, vert); EEPROM.put(8, bleu); boolean ok = EEPROM.commit(); Serial.println((ok) ? "Commit initialisation couleur OK" : "Commit initialisation couleur raté"); } } void choixCouleur(){ WiFiClient client = serveurPOCL.available(); // On écoute si il y a des connexions sur le site web du POCL (des clients) if (client) { // Si il y a une nouvelle connexion, currentTime = millis(); previousTime = currentTime; Serial.println("Nouveau client connecté"); // print a message out in the serial port String currentLine = ""; // créer une chaîne pour contenir les données entrantes du client while (client.connected() && currentTime - previousTime <= timeoutTime) { // Boucle "while", tant que le client est connecté currentTime = millis(); if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // Affiche la page web client.println(""); client.println(""); client.println(""); client.println(""); client.println(""); client.println("

Choisi la couleur de ton POCL

"); client.println("Change de Couleur "); client.println("
"); client.println(""); // The HTTP response ends with another blank line client.println(); // Request sample: /?r201g32b255& // Red = 201 | Green = 32 | Blue = 255 if(header.indexOf("GET /?r") >= 0) { pos1 = header.indexOf('r'); // pos1 est la position du caractère r dans la chaine de caractères. pos2 = header.indexOf('g'); // idem pos3 = header.indexOf('b'); pos4 = header.indexOf('&'); redString = header.substring(pos1+1, pos2); // la chaine de caractère juste après pos1 et jusqu'à pos2 est placée dans la variable redString. greenString = header.substring(pos2+1, pos3); // ... blueString = header.substring(pos3+1, pos4); Serial.println(redString.toInt()); // je publie sur le moniteur série Serial.println(greenString.toInt()); Serial.println(blueString.toInt()); rouge = redString.toInt(); // je transforme la chaine de caractère en nombre entier que je met dans la variable rouge vert = greenString.toInt(); bleu = blueString.toInt(); // Je stocke la configuration dans la mémoire du D1 mini EEPROM.put(0, rouge); EEPROM.put(4, vert); EEPROM.put(8, bleu); boolean ok1 = EEPROM.commit(); Serial.println((ok1) ? "Commit couleur OK" : "Commit couleur raté"); } // On sort ("break") de la boucle "while" break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; fade(); // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } } void setup() { Serial.begin(115200); // Ouverture de communication série uint32_t chipid=ESP.getChipId(); snprintf(nomPOCL,25,"Pokou - %08X",chipid); Serial.print("Je suis le POCL "); Serial.println(nomPOCL); EEPROM.begin(16); testEEPROM(); WiFi.mode(WIFI_STA); // la carte D1 mini est mise en mode STATION WiFiManager MonReseauWifi; // on crée l'objet "MonReseauWifi" bool res; res = MonReseauWifi.autoConnect(nomPOCL); // le POCL diffuse un réseau wifi en accès libre nommé "Pokou - xxxxxxxx" xxxxxxx étant l'ID de la carte if(!res) { Serial.println("La connexion n'a pas fonctionnée..."); } else { Serial.println("Vous êtes connecté au Wifi... :-)"); // Print local IP address and start web server Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address : "); Serial.println(WiFi.localIP()); serveurPOCL.begin(); //démarrage du serveur Web du POCL } pixels.begin(); //on initialise le ruban "pixels" pinMode(brocheBouton,INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // on éteint la led du D1 mini // préparation de la connexion au serveur MQTT clientMQTT.begin(BROKER_IP, 1883, net); // (IP, port, Client Wifi défini plus haut) clientMQTT.onMessage(messageReceived); // Si on reçoit un message MQTT, la fonction "messageReceived" est appelée. connect(); // On se connecte } void loop() { pixels.clear(); // éteint tout les pixels pixels.show(); // affiches pixels clientMQTT.loop(); delay(10); // <- fixes some issues with WiFi stability if (!clientMQTT.connected()) { Serial.print("Le POCL "); Serial.print(nomPOCL); Serial.println(" est déconnecté du serveur MQTT"); connect(); } // Si on appuie sur le bouton, on envoie un messagge MQTT "pokou", sur le topic "/Poke" if ( digitalRead(brocheBouton) == LOW ){ Serial.print("Appuis Bouton du POCL "); Serial.println(nomPOCL); clientMQTT.publish("/Poke", "pokou"); delay(250); // Filtre anti-rebond du bouton } choixCouleur(); // appel de la fonction qui génère la page web de configuration de la couler du POCL }