====== 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}]