====== Stage LPH: février 2019 ====== ===== Introduction ===== Stage LPH de février à L'UBO Open Factory L'objectif de cet atelier est de réaliser une petite station météo et domotique à base d'arduino. ^ Public cible | 12 jeunes | ^ Date | 18, 19 et 20 février | ^ Lieu | **UBO Open Factory** | ===== Modalités ===== Une inscription est nécessaire pour pouvoir planifier. Une adhésion (de 20 euros) et une participation financière (60 euros) pour le matériel (en fonction du projet) seront demandées. * [[interne:pouradherer|Bulletin d'adhésion]] ===== Planning et contenu ===== * Communication * Inscription et vérification de la faisabilité du projet (en compétences, en temps, en matériels si besoin et en coût matériel) * Validation inscription et devis matériel * Planification du projet sur la semaine de mai (en fonction du temps...) ===== État du stock et matériel pour le stage ===== Stock à vérifier en fonction des projets. Voici une première liste de matériel à apporter avec nous pour le stage: ^ Intitulé ^ Quantité dans le stock ^ A commander/produire ^ | Servo moteur (1 par kit) | | | | Arduino nano (avec câble USB) | | | | Câbles élec | | | | écran pour le vidéo-projecteur | | vidéo-projecteur | | 2 rallonges | | 4 multiprise | | 12 PCs: (j'en ai déjà 5 de prêt, il m'en reste 2/3 à préparer) | | alimentations PC | | souris PC | | 12 cartes arduinos (avec cordons USB) | | 12 DHT 11 | | 12 relais | | 12 transistors | | 12 servo moteurs | | 12 LDR | | 12 ventilateurs | | cartes de support pour les éléments | | fils de connexion | | 3/4 fers à souder | | 4 tapis pour fer à souder | | 4 support fer à souder | | étain | | fils | | en option (afficheurs LCD, module bluetooth) | ===== Liste de tâches ===== ^ Tâche ^ Qui ^ Opération ^ | Faire l'état du stock| Christian et Stéphane | | | Commande matériel | Christian et Stéphane | | | Communication sur les listes de diffusion | Christian et Stéphane | | | Communication "Affiche" | | | | Gestion des inscriptions | | | | Validation des inscriptions | | | | Planification des projets | | | ===== Présent pour animer ===== Animation de l'atelier: * Stéphane Blanc * Christian Jacolot * ... ===== Déroulé du projet ===== * Présentation du projet * Validation du matériel (kit arduino) et des logiciels installés sur le PC * Montages: * capteur température * capteur de lumière * programmation arduino * programmation visuelle et affichage des valeurs des capteurs * Montages: * servo moteur * relais * programmation arduino * programmation visuelle et contrôle des automatismes ===== Contacts ===== ^ Structure ^ Nom Prénom ^ Rôle sur le projet / poste ^ | Maison du libre | Stéphane Blanc | Logistique et animation | | Maison du libre | Christian JACOLOT | Logistique et animation | === Remerciements === Nous remercions Yves et Matthieu pour accueillir le stage dans les locaux de l'UBO Open Factory. === Préparation des PC === Installation de xubuntu 18.04 sur les PC, iso sur clé USB. Mise à jour et installation des logiciels/paquets nécessaires: $ sudo apt update $ sudo apt upgrade $ sudo apt install git mercurial build-essential arduino-core arduino-mk gcc-avr avr-libc openjdk-8-jdk $ sudo apt install squeak-vm squeak-plugins-scratch $ sudo apt install nodejs npm $ id $ sudo usermod -a -G dialout $USER $ more /etc/group # télécharger arduino sur arduino.cc / linux 32 bits $ cd Téléchargements/ $ tar xf arduino-1.8.8-linux32.tar.xz $ cd arduino-1.8.8/ $ ./install.sh $ cd # démarrer arduino IDE # menu Outils / Gérer les bibliothèques # installer: circuit playground, unified sensor, DHT sensor library $ sudo npm install -g --unsafe-perm node-red $ node-red # navigateur web sur localhost:1880 # installer via palette: node-red-node-serialport et node-red-dashboard $ sudo apt install logisim openssh-server $ sudo apt install gcc-avr avr-libc flashplugin-installer algobox blender python3-dev python3-setuptools python3-numpy $ sudo apt install python3-opengl ffmpeg libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev libtiff5-dev libx11-6 libx11-dev fluid-soundfont-gm timgm6mb-soundfont xfonts-base xfonts-100dpi xfonts-75dpi xfonts-cyrillic fonts-freefont-ttf libfreetype6-dev $ java -version $ javac -version $ sudo update-alternatives --config java # choisir java 8 $ java -version $ sudo add-apt-repository ppa:openscad/releases $ sudo apt update $ sudo apt install openscad $ sudo apt install fritzing fritzing-parts gimp === Présentation === == Documents == Fichier de présentation {{ :projets:2019:mdl_stage_lph_fevrier_2019.odp |}} === Code === Code Arduino pour piloter le relai tout en récupérant la température et l'humidité: int relayPin = 3; // relay pin -- Digital 3 int relayState = HIGH; int incomingByte = 0; // for incoming serial data unsigned long previousMillis = 0; long checkDHT = 2000; void setup() { Serial.begin(9600); pinMode(relayPin, OUTPUT); digitalWrite(relayPin, relayState); previousMillis = millis(); } void loop() { // send data only when you receive data: if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read(); // Serial.print("I received: "); // Serial.println(incomingByte, DEC); if (incomingByte == 49) { // ASCII: 1 => 49 relayState = HIGH; } else { relayState = LOW; } } unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= checkDHT) { previousMillis = currentMillis; // Remember the time Serial.print("{\"hum\":"); Serial.print(random(20,80)); Serial.print(",\"temp\":"); Serial.print(random(0,50)); Serial.println("}"); } // set the relay: digitalWrite(relayPin, relayState); } Nodered flow: {{ :projets:2019:mdl_stage_nodered_capteur_relai.png?400 |}} Avec servo moteur #include #include VarSpeedServo myservo; // create servo object to control a servo // twelve servo objects can be created on most boards int pos = 0; // variable to store the servo position int positionServo = 0; int speedServo = 100; // Serial reading buffer const byte numChars = 60; char receivedChars[numChars]; // an array to store the received data boolean newData = false; StaticJsonBuffer<120> jsonBuffer; void recvWithEndMarker() { static byte ndx = 0; char endMarker = '\n'; char rc; while (Serial.available() > 0 && newData == false) { rc = Serial.read(); if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string ndx = 0; newData = true; } } } void setup() { pinMode(9, OUTPUT); myservo.attach(9); // attaches the servo on pin 9 to the servo object Serial.begin(9600); // myservo.write(positionServo, speedServo, true); newData = false; } void loop() { recvWithEndMarker(); if (newData == true) { JsonObject& root = jsonBuffer.parseObject(receivedChars); if (!root.success()) { Serial.println("parseObject() failed"); return; } // Fetch values. // // Most of the time, you can rely on the implicit casts. // In other case, you can do root["time"].as(); if(root.containsKey("servo")) { positionServo = root["servo"][0]; speedServo = root["servo"][1]; // Print values. Serial.println(positionServo); Serial.println(speedServo); // myservo.write(positionServo, speedServo); //, true); // move to 180 degrees, use a speed of 30, wait until move is complete } else { Serial.println("parseObject() servo key not found"); } newData = false; } } Arduino: Programme complet (JSON, relai, ventilo, LDR, DHT11, servo-moteur): #include #include #include "DHT.h" #define LDRPIN 0 #define DHTPIN 2 // Digital pin connected to the DHT sensor #define VENTILOPIN 7 #define RELAIPIN 8 #define SERVOPIN 9 #define DHTTYPE DHT11 // DHT 11 DHT dht(DHTPIN, DHTTYPE); VarSpeedServo myservo; unsigned long time; unsigned long diff; int ldrValue = 0; int relayState = LOW; int ventiloState = LOW; int positionServo = 0; int speedServo = 100; long checkDHT = 2000; // Serial reading buffer const byte numChars = 60; char receivedChars[numChars]; // an array to store the received data boolean newData = false; void recvWithEndMarker() { static byte ndx = 0; char endMarker = '\n'; char rc; while (Serial.available() > 0 && newData == false) { rc = Serial.read(); if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string ndx = 0; newData = true; } } } void setup() { pinMode(VENTILOPIN, OUTPUT); pinMode(RELAIPIN, OUTPUT); // relai, broche en mode sortie pinMode(SERVOPIN, OUTPUT); time = millis(); dht.begin(); myservo.attach(9); // attaches the servo on pin 9 to the servo object Serial.begin(9600); newData = false; } void loop() { StaticJsonBuffer<120> jsonBuffer; recvWithEndMarker(); if (newData == true) { JsonObject& root = jsonBuffer.parseObject(receivedChars); if (!root.success()) { Serial.println("parseObject() failed"); receivedChars[0] = '\0'; return; } if(root.containsKey("servo")) { positionServo = root["servo"][0]; speedServo = root["servo"][1]; myservo.write(positionServo, speedServo, true); } if (root.containsKey("ventilo")) { int ventiloValue = root["ventilo"]; if (ventiloValue == 1) { ventiloState = HIGH; } else { ventiloState = LOW; } } if (root.containsKey("relai")) { int relaiValue = root["relai"]; if (relaiValue == 1) { relayState = HIGH; } else { relayState = LOW; } } else { Serial.println("parseObject() servo key not found"); } newData = false; } diff = millis() - time; if (diff >= checkDHT) { time = millis(); float h = dht.readHumidity(); float t = dht.readTemperature(); // read the value from the sensor: ldrValue = analogRead(LDRPIN); Serial.print("{\"hum\":"); Serial.print(h); Serial.print(",\"temp\":"); Serial.print(t); Serial.print(",\"ldr\":"); Serial.print(ldrValue); Serial.println("}"); } // set the relay: digitalWrite(RELAIPIN, relayState); // set the ventilo: digitalWrite(VENTILOPIN, ventiloState); } Nodered flow [{"id":"3d2aea77.badaf6","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"3f949c8b.e9662c","type":"serial in","z":"3d2aea77.badaf6","name":"Arduino liaison série","serial":"7934b4c5.a4c6ac","x":118.50001525878906,"y":105,"wires":[["58f6c8f2.f84108","ee8168db.c30cd8"]]},{"id":"58f6c8f2.f84108","type":"debug","z":"3d2aea77.badaf6","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":708.5,"y":70,"wires":[]},{"id":"ee8168db.c30cd8","type":"json","z":"3d2aea77.badaf6","name":"","property":"payload","action":"","pretty":false,"x":108.49998474121094,"y":204,"wires":[["47a6359d.a05d6c","ad8bab3b.6151e"]]},{"id":"47a6359d.a05d6c","type":"debug","z":"3d2aea77.badaf6","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":709.5,"y":162,"wires":[]},{"id":"ad8bab3b.6151e","type":"function","z":"3d2aea77.badaf6","name":"Récupérer Humidity","func":"msg.payload = msg.payload.hum;\nreturn msg;","outputs":1,"noerr":0,"x":156.50001525878906,"y":291,"wires":[["49353fa9.b11378","5aa63008.6e225"]]},{"id":"49353fa9.b11378","type":"ui_chart","z":"3d2aea77.badaf6","name":"","group":"6236518f.ee41e8","order":1,"width":0,"height":0,"label":"Humidité","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"10","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":798.5,"y":274.9999694824219,"wires":[[],[]]},{"id":"5aa63008.6e225","type":"switch","z":"3d2aea77.badaf6","name":"Humidité >= 60","property":"payload.state","propertyType":"msg","rules":[{"t":"gte","v":"60","vt":"num"},{"t":"lt","v":"60","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":147.83338928222656,"y":384.333251953125,"wires":[["13b76f6c.0304c9"],["2c7f8898.6e7d38"]]},{"id":"3a206f96.153a9","type":"ui_button","z":"3d2aea77.badaf6","name":"","group":"6236518f.ee41e8","order":3,"width":0,"height":0,"passthru":true,"label":"Arrêter le ventilo","tooltip":"","color":"","bgcolor":"","icon":"","payload":"2","payloadType":"str","topic":"","x":512.8333740234375,"y":646.3333740234375,"wires":[[]]},{"id":"902a3c34.bdb6d","type":"serial out","z":"3d2aea77.badaf6","name":"Arduino sortie","serial":"7934b4c5.a4c6ac","x":822.833251953125,"y":400.16668701171875,"wires":[]},{"id":"e06793a6.3b1558","type":"ui_switch","z":"3d2aea77.badaf6","name":"","label":"Automatique","tooltip":"","group":"6236518f.ee41e8","order":4,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","x":328.8333740234375,"y":531.3333740234375,"wires":[["77a8e113.0544f"]]},{"id":"77a8e113.0544f","type":"switch","z":"3d2aea77.badaf6","name":"","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":551.8333740234375,"y":552.3333740234375,"wires":[[],[]]},{"id":"13b76f6c.0304c9","type":"function","z":"3d2aea77.badaf6","name":"Démarrer ventilo","func":"msg.payload = \"{\\\"ventilo\\\":1}\\n\"\nreturn msg;","outputs":1,"noerr":0,"x":371.8333740234375,"y":355.66668701171875,"wires":[["902a3c34.bdb6d"]]},{"id":"2c7f8898.6e7d38","type":"function","z":"3d2aea77.badaf6","name":"Arrêter ventilo","func":"msg.payload = \"{\\\"ventilo\\\":0}\\n\"\nreturn msg;","outputs":1,"noerr":0,"x":347.2833251953125,"y":437.73333740234375,"wires":[["902a3c34.bdb6d"]]},{"id":"7934b4c5.a4c6ac","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":true,"responsetimeout":"10000"},{"id":"6236518f.ee41e8","type":"ui_group","z":"","name":"Chambre","tab":"ad170f6e.de74f8","disp":true,"width":"6","collapse":false},{"id":"ad170f6e.de74f8","type":"ui_tab","z":"","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]