odoc Posté(e) Janvier 27, 2019 Posté(e) Janvier 27, 2019 Bonjour tout le monde, un petit thread pour vous présenter un système dont certaines parties pourraient vous intéresser : un système d'impression piloté par la voix avec gestion du stock de bobines Le système fait appel à plusieurs programme/circuit : Un programme de domotique vocal (dans mon cas il s'agit d'un hack de google chrome) qui gère la partie reconnaissance vocale / lancement du programme d'impression Un programme d'impression, qui est capable de lancer CuraEngine pour générer le gcode, obtenir le temps d'impression et la masse de filament nécessaire, et envoyer le gcode à octoprint Une balance maison (imprimée en 3D) à base d'ESP8266 et d'un capteur de poids afin de savoir s'il reste assez de filament ( capteur : https://www.amazon.fr/gp/product/B07G29TKRH/ref=ppx_yo_dt_b_asin_title_o06__o00_s00?ie=UTF8&psc=1) Un lecteur RFID (relié à l'ESP) (https://www.amazon.fr/AptoFun-Reader-Module-Arduino-Raspberry/dp/B01I5DH69Q/ref=sr_1_11?s=electronics&ie=UTF8&qid=1548617383&sr=1-11&keywords=rfid) afin d'identifier chaque bobine grâce à un capteur RFID (https://www.amazon.fr/gp/product/B01EHPZWOC/ref=ppx_yo_dt_b_asin_title_o04__o00_s00?ie=UTF8&psc=1) collé sur chacune d'entre elles. Un site web maison servant de base de donnée, regroupant les différentes info sur chaque bobines (couleur, poids, températures d'impression, balise rfid) et communiquant avec l'ESP via une API sécurisée maison Fonctionnement : Une commande vocale du type "imprime le fichier en noir" va alors entrainer plusieurs actions : une recherche du dernier fichier stl modifié sur le pc la récupération des infos concernant l'impression en noir (température de la buse et du bed) la génération du gcode par curaengine et l'obtention de la quantité de filament nécessaire la récupération d'info concernant la bobine actuellement sur la balance : masse et couleur -> Si la couleur et/ou la masse ne correspondent pas, le filament est retiré via l'envoi d'une commande M600 Lancement de l'impression via octoprint Mise à jour de la quantité de filament dans la bobine jusqu'à la fin de l'impression En dehors du côté fun à la Iron Man, la partie intéressante est la balance qui permet de connaitre en permanence la quantité de filament restant via un site internet : Vous pouvez voir sur ces 2 photos la balance ainsi que le lecteur RFID (le circuit l'électronique avec l'ESP se trouvant dans la boite à l'arrière) : le fonctionnement est simple : si le capteur de poids voit une différence importante (= on retire la bobine), il attends que le lecteur rfid scanne un code, ensuite il attend quelques secondes puis enregistre le poids de la bobine. Enfin, il envoie toutes les infos au serveur qui gère la suite (mise à jour des info de la bobine si celle si est enregistrée dans la BDD ou création d'une entrée dans le cas contraire) Capture d'écran du site de gestion : pour chaque bobine on peut rentrer la température d'impression (de la première couche et des suivantes, pour la buse et le bed) et on voit quelle quantité de filament il reste Voici le code de l'ESP8266 (sous licence GNU GPL v3) (pour la partie web et la partie reconnaissance vocale/slicing ça ne sera pas possible dans l'immédiat, n'étant pas le seul à avoir travailler dessus) : (le code est largement optimisable mais si ça peut en aider certains tant mieux) #include <SPI.h> #include <MFRC522.h> #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266HTTPUpdateServer.h> #include <WiFiClientSecure.h> #include <ArduinoJson.h> #include <Adafruit_NeoPixel.h> #include "HX711.h" #define DOUT 4 #define CLK 5 HX711 scale(DOUT, CLK); //Change this calibration factor as per your load cell once it is found you many need to vary it in thousands #define zero_factor 190860 float oldPoids=0; String myKey=""; String url = "/receive.php"; String host="https://host.fr"; String user="user";//website api String token="token";//website api unsigned long previousMillis ; ESP8266HTTPUpdateServer httpUpdater; // instance pour l'OTA (obligatoire) #define RST_PIN 0 // Configurable, see typical pin layout above #define SS_PIN 15 // Configurable, see typical pin layout above ESP8266WebServer server(7980); const char *SERVER_WIFI_SSID = "XXXX"; const char *SERVER_WIFI_PASS = "XXXX"; String readRFID = "nok"; MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class MFRC522::MIFARE_Key key; WiFiClientSecure client; #define del 2 #define NUMPIXELS 1 Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, del, NEO_GRB + NEO_KHZ800); void setupWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(SERVER_WIFI_SSID,SERVER_WIFI_PASS); // WiFi.setAutoConnect(false); // WiFi.setAutoReconnect(false); while(WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("..."); } Serial.println("connected"); Serial.println(WiFi.localIP()); } void setup() { Serial.begin(9600); pixels.begin(); pixels.setPixelColor(0, 0,0,0); pixels.show(); setupWiFi(); httpUpdater.setup(&server); //on lance l'instance gérant l'OTA server.begin(); //on démarrage le serveur web SPI.begin(); // Init SPI bus rfid.PCD_Init(); // Init MFRC522 rfid.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details scale.set_scale(-212760); //Calibration Factor obtained from first sketch scale.set_offset(zero_factor); server.on("/", [](){ if (server.argName(0)=="poids"){ if (server.arg(0)=="now"){ String poids=String(scale.get_units(5)*1000); //grammes Serial.println(poids); server.send(200, "text/html", poids); } else { if (server.arg(0)=="tare"){ scale.tare(); Serial.println("Tare"); server.send(200, "text/html", "tare"); } else { if (server.arg(0)=="end") { String poids=String(scale.get_units(5)*1000); //grammes Serial.println(poids); sendIFM(myKey,poids,"end"); server.send(200, "text/html", poids); } } } } if (server.argName(0)=="rfid"){ if (server.arg(0)=="ok"){ readRFID="ok"; Serial.println(readRFID); server.send(200, "text/html", readRFID); } else { if (server.arg(0)=="last"){ server.send(200, "text/html", myKey); } } } }); readIFMRFID(); oldPoids=scale.get_units(5)*1000; Serial.println("led"); pixels.setPixelColor(0,255,255,255); pixels.show(); delay(500); pixels.setPixelColor(0, 0,0,0); pixels.show(); delay(500); pixels.setPixelColor(0,255,255,255); pixels.show(); delay(500); pixels.setPixelColor(0, 0,0,0); pixels.show(); previousMillis = millis(); } void readIFMRFID(){ StaticJsonBuffer<200> jsonBuffer; String PostData = "{"; PostData += "\"user\": \""+user+"\","; PostData += "\"token\": \""+token+"\","; PostData += "\"action\": \"esp_rfid\"}"; Serial.println("connexion"); if (!client.connect(host, 443)) { Serial.println("connection failed"); return; } else { Serial.println("connecté"); client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Type: application/json"+"\r\n" + "Content-Length: " + PostData.length() + "\r\n" + "\r\n" + // This is the extra CR+LF pair to signify the start of a body PostData + "\n"); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { Serial.println("headers received"); break; } } String line = client.readStringUntil('\n'); JsonObject& root = jsonBuffer.parseObject(line); const char * tmp = root["rfid"]; myKey = tmp; Serial.print("RFID Key : "); Serial.println(myKey); } } void sendIFM (String uid, String poids, String state){ String PostData = "{"; PostData += "\"user\": \""+user+"\","; PostData += "\"token\": \""+token+"\","; PostData += "\"rfid\": \""+uid+"\","; PostData += "\"action\": \"rfid\","; PostData += "\"state\": \""+state+"\","; PostData += "\"poids\": \""+poids+"\"}"; if (client.connect(host, 443)) { client.print(String("POST ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Type: application/json"+"\r\n" + "Content-Length: " + PostData.length() + "\r\n" + "\r\n" + // This is the extra CR+LF pair to signify the start of a body PostData + "\n"); } } void loop() { server.handleClient(); unsigned long currentMillis = millis(); if (readRFID!="ok"){ float newPoids=scale.get_units(5)*1000; Serial.print("new : "); Serial.println(String(newPoids)); Serial.print("old : "); Serial.println(String(oldPoids)); unsigned long currentMillis = millis(); if (oldPoids-newPoids > 150 && (currentMillis - previousMillis >= 1000)){ pixels.setPixelColor(0,0,0,255); pixels.show(); delay(200); pixels.setPixelColor(0, 0,0,0); pixels.show(); delay(200); pixels.setPixelColor(0, 0,0,255); pixels.show(); delay(200); pixels.setPixelColor(0,0,0,0); pixels.show(); previousMillis = currentMillis; readRFID="ok"; } else { Serial.println("old"); oldPoids=newPoids; Serial.println("oldPoids"); if (currentMillis - previousMillis >= 60000){ sendIFM(myKey,String(newPoids),"end"); previousMillis = currentMillis; Serial.println("maj"); } } } if (readRFID =="ok"){ if ( rfid.PICC_IsNewCardPresent()){ if (rfid.PICC_ReadCardSerial()){ myKey=String(rfid.uid.uidByte[0],HEX)+ String(rfid.uid.uidByte[1],HEX) + String(rfid.uid.uidByte[2],HEX) + String(rfid.uid.uidByte[3],HEX); pixels.setPixelColor(0,255,255,255); pixels.show(); delay(200); pixels.setPixelColor(0,0,0,0); pixels.show(); delay(200); pixels.setPixelColor(0, 255,255,255); pixels.show(); delay(5000); String poids=String(scale.get_units(5)*1000); pixels.setPixelColor(0,0,0,0); pixels.show(); delay(200); pixels.setPixelColor(0, 0,0,255); pixels.show(); delay(200); pixels.setPixelColor(0, 0,0,0); pixels.show(); delay(200); pixels.setPixelColor(0, 0,0,255); pixels.show(); delay(200); pixels.setPixelColor(0, 0,0,0); pixels.show(); oldPoids=poids.toFloat(); Serial.print("poids : "); Serial.println(String(poids)); sendIFM(myKey,poids,"new"); rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); readRFID="nok"; } } } delay(200); } Bonne fin de week end.
Janpolanton Posté(e) Janvier 27, 2019 Posté(e) Janvier 27, 2019 Salut, Intéressant, mais quand je vois ce que ça donne quand je dicte un sms, j'ai peur du résultat... 1
odoc Posté(e) Janvier 27, 2019 Auteur Posté(e) Janvier 27, 2019 il y a 3 minutes, Janpolanton a dit : Salut, Intéressant, mais quand je vois ce que ça donne quand je dicte un sms, j'ai peur du résultat... En fait la reconnaissance vocale de chromium marche plutot bien (alors que c'est sur un Rpi avec un simple micro USB), après y a un programme (serveur php) derrière qui filtre la réponse et s'assure d'avoir un bon taux de correspondance entre le texte traduit et la commande attendue. Mon système me permet de gèrer toute ma domotique et j'ai jamais eu de faux positifs pour le moment (et concernant ce système en particulier, il ne peut de toute façon rien se passer si l'imprimante est éteinte ou si elle imprime déjà ^^). Bon pour la reco vocale le gros problème c'est de passer par les serveurs de google :s (mais le système se pilote aussi via une appli android ou un bete navigateur web)
Janpolanton Posté(e) Janvier 27, 2019 Posté(e) Janvier 27, 2019 Je ne confierais pas la sécurité de mes biens et de mes proches à une appli de reconnaissance vocale. Ce n'est que l'avis d'un vieux croûton de 66 ans...
odoc Posté(e) Janvier 27, 2019 Auteur Posté(e) Janvier 27, 2019 il y a 8 minutes, Janpolanton a dit : Je ne confierais pas la sécurité de mes biens et de mes proches à une appli de reconnaissance vocale. Ce n'est que l'avis d'un vieux croûton de 66 ans... vu que je vis tout seul, ça va mais je suis d'accord. Mais faut aussi voir qu'une bete appli android/navigateur web permet de commander le système aussi bien. La reco vocale n'est qu'un plus et j'espère un jour pouvoir me passer de google via le projet de Mozilla par exemple. Concernant ce projet en particulier, actuellement j'utilise surtout la partie gestion des bobines qui est quand même franchement pratique (rien que pour savoir s'il me reste assez de PLA pour lancer l'impression)
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant