Overblog Suivre ce blog
Administration Créer mon blog
24 février 2017 5 24 /02 /février /2017 11:58

Une fois encore l'inspiration m'est venue en lisant l'excellente revue Hackable. Et une fois encore je me suis dis que c'était sympa mais que je pouvais faire mieux ;)

J'ai donc décidé de restaurer deux lampes à pétrole données par un ami à qui j'avais eu la bonne idée de faire part de mon projet ;) avec les objectifs suivants:

  • Aucune consommation d'énergie quand la lampe est éteinte
  • Différents modes d'éclairages
  • Réutilisation de la commande de la mèche de la lampe pour régler l'intensité et/ou la couleur de la lampe.
  • Réutilisation (quand c'est possible) du bouchon du réservoir pour changer de mode d'éclairage.

J'ai une grande et une petite lampe. J'ai rapidement vu que je ne pourrai pas loger le contacteur rotatif à 2x6 contacts sous le bouchon du réservoir de la petite. La petite lampe utilisera donc le poussoir de l'encodeur rotatif pour changer de mode d'éclairage. L'encodeur rotatif étant accouplé à la commande de la mèche (plus de détails plus loin).

Côté éclairage, j'ai commandé des couronnes de LED WS2812B de différents diamètres qui feront très bien l'affaire.

Côté micro-contrôleur, l'ATMega328P est tout indiqué. Il me reste encore quelques unes des géniales cartes Evil-Mad Scientist qui sont tout à fait adaptées à ce besoin. C'est bien plus propre qu'une plaque à trous et bien plus simple que de devoir faire son propre circuit imprimé.

Les différents modes d'éclairage que j'ai envie de proposer sont:

  • Eclairage fixe et réglage de l'intensité via la molette
  • Eclairage fixe et réglage de la couleur via la molette
  • Eclairage "arc-en-ciel" fixe et réglage de l'intensité via la molette
  • Eclairage "arc-en-ciel" rotatif et réglage de l'intensité via la molette
  • Eclairage "simulateur de flamme"

 

Lanternes brutes avant restauration

Lanternes brutes avant restauration

Schéma électrique de la grande lanterne (avec contacteur rotatif):

Schéma électrique de la petite lanterne (sans contacteur rotatif):

 

Manette de commande

J'ai eu pas mal de boulot côté hardware: découpes au Dremmel, modélisation et impression 3D.

Il a tout d'abord fallu démonter le mécanisme d'alimentation de la mèche et trouver où placer l'encodeur rotatif en prolongement avec l'axe du mécanisme. Le disque de découpe du Dremmel fut un outil précieux dans cette tâche!

Pour coupler la manette avec l'encodeur j'ai essayé deux méthodes:

Pour la première lanterne où j'avais pas mal de place j'ai utilisé du plastique EasyPlast (qui fond à 60°) trempé dans de l'eau chaude puis modelé à la main et au pistolet à air chaud. Ce plastique est  quand même vachement pratique car ça permet modeler à la main des pièces très solides après refroidissement.

 

 

Pour la seconde j'ai usiné le bout de la manette pour qu'il entre à forcer dans l'encoche de l'axe de l'encodeur rotatif.

 

 

 

 


 

Support de LEDs et Diffuseur

J'ai modélisé un support paramétrable pour les anneaux de LED (avec OpenScad) afin de pouvoir poser l'anneau à plat tout en ménageant un espace pour les soudures et les câbles.

Le modèle est disponible dans le dépôt github donné à la fin de ce billet.

 

Il m'a fallu aussi modéliser un diffuseur. J'ai fait pour cela un modèle paramétrique dans OpenScad qui permet de modéliser une calotte sphérique avec un diamètre, une hauteur et une épaisseur paramétrable. J'ai ainsi imprimé des diffuseurs adaptés à chaque lampe, en PLA transparent.

 

Support de la carte électronique

J'ai aussi eu besoin d'un support pour fixer la carte électronique au fond du réservoir.

Là j'ai opté pour Fusion360 qui m'est bien plus simple à utiliser pour ce genre de pièce (le modèle est disponible dans le dépôt github).

J'ai imprimé un support adapté à chaque taille de lampe, fixé par deux vis dans une découpe du fond du réservoir.

Support de la petite lanterne:

 

Fixation du contacteur rotatif

Après avoir réfléchi à plusieurs solutions pour fixer le contacteur rotatif sous le bouchon de réservoir de la grande lanterne j'ai fini par modéliser une bride de fixation (avec Fusion360) sur laquelle le contacteur est vissé, et qui est collée à la colle époxy à l'intérieur du réservoir.

Modèle de la bride de fixation du contacteur

bride collée

 

J'ai aussi usiné un méplat sur l'axe du contacteur.

Enfin concernant le bouchon du réservoir, j'ai dû meuler son pas de vis, percer un trou en son centre et y faire un méplat en collant une barrette métallique à la colle époxy.

Il ne restait plus qu'à faire la partie logicielle :)

 

Logiciel

Côté logiciel j'ai commencé par utiliser la librairie WS2812FX, qui utilise la librairie Neopixel d'Adafruit. Elle n'est pas mal, elle dispose de plein d'effets, mais rien qui ne me convenait.

C'était une bonne occasion d'utiliser la librairie FastLED dont j'avais entendu parler par ailleurs. Elle est relativement bien documentée mais surtout bien plus compacte (et très portable).

J'ai pu sans problème faire ce dont j'avais besoin.

Pour la partie simulateur de flamme, j'ai fait plusieurs essais pas vraiment convaincants et je suis revenu à celui que je préfère pour ce genre d'usage: Celui-ci. Je l'ai simplement adapté pour utiliser FastLED pour piloter mes LED et pour permettre de sortir facilement d'une boucle de simulation quand on change de mode d'éclairage.

C'était la première fois que j'utilisais un encodeur rotatif. J'ai essayé diverses librairies pour finalement retenir celle de PJRC. Elle a l'avantage de pouvoir fonctionner avec ou sans interruptions, d'être simple à mettre en oeuvre et de permettre d'initialiser la valeur que manipule l'encodeur.

Les valeurs de luminosité, de couleur, et de mode (pour la petite lanterne uniquement) sont stockées dans l'EEPROM afin que la lampe se rallume dans le même état qu'elle s'est éteinte (les valeur ne sont écrites qu'en cas de modification).

Le code est commenté, il ne devrait pas poser de problème à ceux qui souhaiteraient le réutiliser.

Le code, le schéma électrique et les modèles 3D sont disponibles sur ce dépôt github.

 

Le résultat final:

 

Repost 0
Published by breizhmakers
commenter cet article
23 février 2017 4 23 /02 /février /2017 18:15
Repost 0
Published by breizhmakers
commenter cet article
18 février 2017 6 18 /02 /février /2017 14:11

Ma femme souhaitait disposer d'un sonomètre lumineux afin que ses élèves voient vraiment combien ils sont parfois bruyants :)

J'ai un Sonomètre WENSN WS1361 déjà mis en oeuvre sur un autre projet.

L'idée là est d'avoir un bargraphe lumineux, avec seuil maximal réglable, et la valeur de pic qui reste allumée pendant plusieurs secondes.

Du côté du logiciel, j'ai réutilisé le code Python permettant d'accéder au Sonomètre, en l'adaptant à mon besoin.

Le bargraphe est constitué de deux barres de LED WS2812B (NeoPixel) et piloté via l'excellente librairie  rpi_ws281x. Un exemple d'utilisation est donné sur le site de Adafruit.

Attention: Avec mon RPi3 j'ai dû désactiver l'audio sur le HDMi car ça empêchait le fonctionnement correct de la librairie. Il faut pour cela commenter/ajouter les lignes suivantes au fichier /boot/config.txt.(plus d'infos ici):

#dtparam=audio=on
hdmi_force_hotplug=1
hdmi_force_edid_audio=1

 

Concernant le réglage du seuil maximal, le RPi ne dispose malheureusement pas d'entrée analogique. Comme je voulais garder le montage le plus simple possible, j'ai eu recours à un montage à base de filtre R variable / C branché sur une sortie et une entrée numérique. La mesure de la position du potentiomètre se traduit par une mesure de temps de charge du condensateur, qui lui est proportionnel. C'est rustique et relativement peu précis, mais très suffisant pour l'usage envisagé. Le code dont je me suis inspiré est celui-ci.

J'ai ensuite fait de ce script Python un service SystemD afin qu'il démarre automatiquement au boot. Je me suis inspiré de cet article.

Tout le code est disponible sur ce dépôt GitHub.

Premier prototype, sans boîtier ni diffuseur:

Prototype sans boitier

Côté Hardware j'ai imprimé un boitier pour RPi3 trouvé sur Thingiverse, que j'ai ensuite usiné au Dremmel pour y ménager les ouvertures pour passe les câbles et l'axe du potentiomètre de réglage. 

Le diffuseur est constitué d'un morceau de plastique translucide de récupération sur lequel j'ai collé à la colle chaude les 2 barres de 8 LED Neopixel ainsi que l'adaptateur de niveau 3.3v vers 5v

La base du diffuseur a été modélisée sur Fusion360 (mon outil préféré, avec Openscad pour les pièces paramétriques) et imprimée à la maison.

 

 

 

 

 

 

 

 

 

 

 

 

Le sonomètre lumineux terminé, alimenté par une batterie:

Sonomètre lumineux terminé

 

Le système est depuis utilisé couramment en classe et fait l'unanimité chez les professeurs! :)

J'ai beaucoup de demande et je commence à réfléchir à une version plus compacte et ne nécessitant pas un sonomètre externe.

 

Une petite vidéo de démonstration: 

Repost 0
Published by breizhmakers
commenter cet article
1 novembre 2016 2 01 /11 /novembre /2016 13:15

Cette année j'avais envie de faire un truc bruyant et lumineux pour Halloween. Et forcément, ça devait faire peur :)

Je me suis d'abord mis en quête de sons d'Halloween effrayants, et j'ai trouvé mon bonheur en quelques minutes.

La partie logicielle principale est  faite en Processing. Un outil vraiment très sympa pour du développement rapide et facile (ainsi que pour l'apprentissage de l'informatique sous une forme créative). 

Reste ensuite à savoir comment déclencher le truc via un appui sur la sonnette et à transmettre l'info au code en Processing.

Le moyen le plus simple est d'utiliser le réseau Wifi de la maison pour cela. Ca tombe bien j'ai un ESP8266 sous la main. Le truc a l'avantage d'avoir une carte WIFI intégrée et se programme en C facilement avec l'IDE Arduino. J'ai prévu un circuit électrique isolé via un optocoupleur, passant par le bouton de la sonnette car avant d'ouvrir le boitier je pensais que le bouton était alimenté en 230V, alors qu'il est en fait alimenté en 9V alternatif.  J'ai donc temporairement débranché l'inter de son transformateur pour l'insérer dans mon circuit, via une alimentation de récup' en 7.5V continu.

Lorsqu'on appuie sur la sonnette, ça envoie simplement un caractère via une socket réseau au programme en Procesing qui tourne dans le garage.

Le code dans l'ESP est le suivant:

 

 

/**
* "interrupteur sans fil" rudimentaire.
**/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

//pin mapping
#define D0 16
#define D1 5
#define D2 4
#define D3 0
#define D4 2
#define D5 14
#define D6 12
#define D7 13
#define D8 15
#define D9 3
#define D10 1

#define DEBUG
#define PIN_LED D10
#define PIN_BUTTON D5

//wifi network name
const char* ssid = "monRéseau";
//wifi network password
const char* password = "monPwd";

ESP8266WiFiMulti WiFiMulti;
WiFiClient client;

void connectWifi(){
#ifdef DEBUG
Serial.print("Connecting to ");
Serial.println(ssid);
#endif
WiFiMulti.addAP(ssid,password);
delay(500);
while (WiFiMulti.run() != WL_CONNECTED) {
delay(500);
}
#ifdef DEBUG
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
#endif
}

void disconnectWifi(){
#ifdef DEBUG
Serial.println("Disconnecting Wifi");
#endif
WiFi.disconnect();
}

void setup() {
#ifdef DEBUG
Serial.begin(9600);
while (!Serial); // wait for serial attach
delay(5000);
digitalWrite(PIN_LED,HIGH);
delay(250);
digitalWrite(PIN_LED,LOW);
#endif

connectWifi();
}

//Connexion au PC distant, provoque le démarrage de l'animation
void sendCommand(){
if (!client.connect("192.168.1.12", 12345)) {
Serial.println("connection failed");
return;
}
client.print(65);
client.flush();
client.stop();
}

void loop() {
if(digitalRead(PIN_BUTTON)){
Serial.println("bouton!");
digitalWrite(PIN_LED,HIGH);
sendCommand();
digitalWrite(PIN_LED,LOW);
//simple debouncing
delay(100);
while(digitalRead(PIN_BUTTON));
}
delay(50);
}


Côté Processing il s'agit de jouer des sons associés à des animations lumineuses de circonstance.

Sur le "rire machiavélique" j'ai rapidement eu l'idée d'un fade-in & fade-out entre le rouge et le noir, avec en surimpression une tête de monstre qui apparaîtrait à travers une des fenêtres du garage.

Sur le cri du monstre l'idée était de surprendre et de faire peur et j'ai pas mal tâtonné pour arriver à faire une succession de flashes blanc, noir et rouges à une fréquence variable et aléatoire.

L'animation est déclenchée par un clic (c'est pratique pour tester) et lors de la connexion de l'interrupteur wifi, lorsque quelqu'un sonne à la porte.

Le code est celui-ci:

import processing.net.*;

import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;

Minim minim;
AudioPlayer player;
AudioInput input;
Server srv;
Client client;
boolean pressed=false;
int anim=0;
int count=0;
int speed=2;
PImage img;

//dessine le monstre à la bonne taille & position
void drawMonster(){
float scaleFactor = 0.45;
int x = 86;
int y = height - int(img.height * 0.7) ;
image(img,x,y,img.width*scaleFactor,img.width*scaleFactor);
}

void setup()
{
fullScreen();
frameRate(50);
background(#000000);

img = loadImage("monster.png");
minim = new Minim(this);
//se met en attente des conexions de l'interrupteur wifi
srv = new Server(this, 12345);
noStroke();
}

//boucle principale
void draw(){
if (keyPressed == true && pressed == false) {
mousePressed();
pressed = true;
}
if(keyPressed == false){
pressed = false;
}
client = srv.available();
if (client != null) {
client.read();
mousePressed();
}

//séquencement des deux animations
switch (anim){
case 1:
anim1();
break;
case 2:
anim2();
break;
}

count++;
}

void mousePressed()
{
if(anim==0){
count=0;
anim=1;
}
}

//première animation: monstre & flashes
void anim1(){
if(player == null){
player = minim.loadFile("Monster.mp3");
player.play();
}
int modulo = count % speed;
if(modulo >= 0 && modulo <= 1)
background(modulo ==0?#FFFFFF:#FF5555);
else
background(#000000);

speed = floor(count/50)+2;
if(count >= 7.5*50){
anim=2;
count=0;
player = null;
}
}

//seconde animation: rire machiavélique & fade-in-out en rouge
void anim2(){
if(player == null){
player = minim.loadFile("Evil_Laugh.mp3");
player.play();
}
int modulo = count % 1;
if(modulo == 0){
colorMode(HSB, 100);
int b = round(abs(sin(((float)count/1.5)/360*TWO_PI)*100));
background(color(0,100,b));
}
if(count >= 9.5*50){
background(#000000);
anim=0;
player=null;
}
drawMonster();
}

Pour ajouter plus de réalisme à la chose je voulais faire bouger la porte du garage en même temps que le monstre rugit.

N'ayant pas de moteur électrique assez puissant sous la main pour faire un truc qui cogne fort contre la porte, j'ai pris le plus gros moteur pas à pas que j'avais, récupéré sur un photocopieur.

Son rôle est de tirer à plusieurs reprises sur la porte du garage pour qu'elle bouge comme si on essayait de l'ouvrir.

Il est commandé par un Arduino. La séquence de mouvements de déclenche par un capteur de luminosité (dès que les flashes de l'animation démarrent). Le capteur s'auto-calibre au démarrage du sketch et démarre les mouvements si la luminosité mesurée dépasse le seuil déterminé au démarrage de plus de 15%. Ca permet de rendre le truc relativement indépendant de la luminosité ambiante.

 

 

Le code est le suivant:

#include <Stepper.h>

#define INITIAL_DELAY 2000
#define PIN_LDR A0
#define THRESHOLD_FACTOR 1.15

const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 2, 3, 4, 5);
int light=0;
int threshold=0;
int running=0;

//auto-calibrage de la luminosité ambiante au démarrage
void calibrate(){
delay(150);
threshold = analogRead(PIN_LDR);
}

//désactive toutes les sorties pilotant le moteur pas à pas
void disableOutputs(){
digitalWrite(2,LOW);
digitalWrite(3,LOW);
digitalWrite(4,LOW);
digitalWrite(5,LOW);
}

void setup() {
myStepper.setSpeed(200);
calibrate();
}

//boucle principale
void loop() {
if(analogRead(PIN_LDR) > threshold * THRESHOLD_FACTOR){
running = 1;
}
if(running){
delay(INITIAL_DELAY);
myStepper.step(stepsPerRevolution*3+4);
disableOutputs();
delay(1500);
myStepper.step(stepsPerRevolution+4);
disableOutputs();
running = 0;
}
}

Un résumé en images.

Le truc a bien fonctionné  :)

 

Repost 0
Published by breizhmakers - dans Arduino ESP8266
commenter cet article
19 juin 2016 7 19 /06 /juin /2016 22:00

Depuis que j'ai découvert le bac à sable "augmenté" de Lakeviz j'ai eu envie d'en faire un.

Il se trouve que le chercheur auteur du site et du logiciel a eu la bonne idée de mettre le logiel en open-source, et surtout de documenter la procédure d'installation et de calibrage d'une façon exceptionnelle. Ca simplifie grandement la mise en oeuvre!

J'ai modifié cette procédure pour l'adapter à mon cas d'usage où l'image projetée n'est pas exactement de la taille du bac à sable. Je ne vais pas reprendre ici tous les détails de la procédure "officielle", extrêmement bien documentée ici, mais seulement donner quelques explications complémentaires.

Pré-requis

  • Il faut impérativement un ordinateur équipé d'une carte graphique nVidia (une carte moyen de gamme suffit).
  • Le système d'exploitation requis est Linux. J'ai choisi la version Linux Mint recommandée, sur laquelle j'ai ensuite installé le pilote graphique nVidia propriétaire requis.
  • Une Kinect Version 1 et un adaptateur pour PC (disponible pour une quinzaine d'euros sur ebay par exemple) afin de pouvoir la brancher sur un port USB.
  • Le vidéoprojecteur utilisé doit être HDMI, de préférence avec une résolution supérieure ou égale à 1024 x 768 pixels, et avec une courte focale, afin de pouvoir avoir une grande image sans trop d'éloignement.

Construction du bac à sable

Aucune indication n'est donnée quant à la construction du bac à sable et du support de projecteur.

La dimension recommandée est d'environ 1m x 0.75m sur 15cm de profondeur.

Je recommande plutôt de mesurer la taille de l'image obtenue avec le projecteur souhaité à une distance de 1.20m environ et de construire le bac à sable à cette dimension.

Mon bac à sable fait donc 1m x 0.75m sur 17.5cm de profondeur.

Il est assemblé à partir de planches découpées et d'un fond de contreplaqué de 15mm d'épaisseur.

Les angles des planches sont "crantés", c'est un peu galère à découper au ciseau à bois mais je trouve que ça offre la meilleure solidité. Le tout est collé et vissé.

J'ai ajouté 4 poignées métalliques pour faciliter le transport.

Le support de vidéoprojecteur est construit à base de profilé en U de 1m de longueur et 20mm de côté et d'équerres métalliques vissées sur ce profilé.

Je conseille plutôt du profilé rectangulaire assez solide (genre 20mm x 35mm) car mon support, bien que solide, est un peu trop souple et oscille quand on le touche.

Le vidéo-projecteur est posé sur une planche en médium.

Le miroir est quant à lui un simple miroir de salle de bain, avec des supports en tasseau, des petites équerres-butées et quelques points de colle chaude. J'avais initialement mis le miroir à 45° mais avec mon projecteur il vaut mieux quelques degrés de plus pour avoir une image centrée.

Enfin le support de la Kinect est constitué de 4 équerres collées à la super-glu sur les profilés alu et de colliers auto-serrants. Il y a juste assez de jeu pour pouvoir enlever la Kinect en la faisant glisser dans son support.

Là encore, en l'absence de documentation sur comment construire un support optimal, cette solution n'est pas la meilleure, car la Kinect ne voit pas tout à faire tout le bac à sable. Il vaudrait mieux soit augmenter un peu la hauteur du support, soit placer la Kinect sur les profilés plutôt qu'au-dessous tel que je l'ai fait.

En ce qui concerne le sable proprement dit, j'ai utilisé du sable blanc de décoration. Il faut compter entre 50 et 75 Kg de sable.

Bac à Sable augmenté DIY

Bac à Sable augmenté DIY

Installation des logiciels et calibrage

L'installation et la compilation des logiciels n'est pas vraiment problématique, même s'il vaut mieux connaitre un peu Linux pour être plus à l'aise.

La procédure de calibration, bien que très bien documentée (pour qui lit et comprend l'anglais) est plus compliquée. Enfin il ne m'a quand même fallu que deux tentatives pour que ça fonctionne parfaitement.

J'ai suivi la procédure décrite ici avec des ajustements car l'image de mon projecteur ne couvre pas tout le bac à sable.

A l'étape 7, "calculate your sandbox base plane", j'ai simplement pris des mesures sur une zone plus petite que celle indiquée afin d'être sûr de ne mesurer que le fond du bac à sable (cette étape établit une équation du plan du fond du bac à sable par rapport à la Kinect).

A l'étape 8, "Measure the 3D extents of the sand surface", comme j'avais du mal à déterminer les limites de l'image sur la vue "depth image" de la Kinect, j'ai procédé en deux séries de mesures:

J'ai utilisé un cylindre d'environ 10cm de hauteur et 2 cm de diamètre, que j'ai placé pour chaque mesure, sur le coin dont on mesure les coordonnées (dans l'ordre spécifié par la doc, c'est indispensable).

Une fois les mesures sur les 4 coins réalisées, j'ai refait une série de mesures en prenant cette fois un point légèrement à l'intérieur de la sandbox par rapport à mon point précédent, de façon à ce que la valeur sur l'axe Z mesurée soit bien la hauteur entre la kinect et le fond de la boite.

J'ai ensuite remplacé les 4 mesures sur l'axe Z précédentes par les valeurs mesurées lors de la seconde série de mesures.

Ainsi j'ai à la fois les coordonnées X, Y et Z de chaque point exactes.

Après avoir complété le fichier BoxLayout.txt avec les infos précédentes, le plus dur est fait.

Il reste alors à faire l'outil de calibrage indiqué, à l'aide d'un vieux CD, un peu de papier et de fil de fer, puis à procéder à la dernière partie du calibrage consistant à calibrer l'image vue par la Kinect et celle affichée par le projecteur (étape 10).

Une fois cette étape effectuée il ne reste plus qu'à lancer l'application SARndbox et à profiter de la magie d'un bac à sable augmenté!

Démo du bac à bable augmenté

Repost 0
Published by breizhmakers
commenter cet article
31 mai 2016 2 31 /05 /mai /2016 20:30
Un Sonomètre connecté en OpenTSDB

Ayant fait l'acquisition d'un Sonomètre WENSN WS1361 j'ai rapidement cherché à en exploiter les mesures automatiquement.

Après une tentative infructueuse d'utiliser sa sortie analogique, au comportement instable et pour le moins étrange, j'ai préféré utiliser son port USB.

Dans ce monde merveilleux de l'open-source il se trouve que quelqu'un a eu la bonne idée de faire un reverse-engineering du protocole de ce sonomètre et de mettre gracieusement le script python à disposition.

OVH met gratuitement à disposition un serveur OpenTSDB ainsi que des exemples de code dans différents langages, dont Python.

Après quelques adaptations à Python 3 on a une API fonctionnelle de haut niveau, très simple à utiliser.

Le script envoie une mesure toutes les 5 minutes. C'est bien sûr paramétrable tel qu'indiqué dans le README.md du dépôt github.

Cette mesure est une moyenne mobile des 5 dernières minutes. Le capteur fournit, lui, une mesure toutes les 2s, qui est aussi une moyenne mobile sur 2s, envoyée elle aussi une fois toute les 5 minutes et remise à zéro après envoi.

Ces métriques sont envoyée sous les noms:

soundLevel et soundLevel.peak

Le script est lancé au démarrage de l'ordinateur.

Il est possible que je l'installe un jour sur un Raspberry pi.

J'utilise Grafana pour afficher les métriques stockée dans OpenTDSB:

Repost 0
Published by breizhmakers
commenter cet article
14 mai 2016 6 14 /05 /mai /2016 20:50

Il commence à faire chaud dans mon bureau et dans mes combles et j'avais envie de pouvoir mesurer la température avec plus de précision que le bout de mon nez :)

 

L'ESP8266 est une solution remarquablement adaptée pour cela avec sa connectivité wifi (et HTTPS) intégrée et son faible coût.

J'utilise la version NodeMCU (programmée en C) car pour seulement quelques euros de plus j'ai un port USB et une alimentation 5V via l'USB.

Le capteur de température est un DHT22, bien plus précis qu'un DHT11 et pas beaucoup plus cher.

Carte NodeMCU et capteur DHT22Carte NodeMCU et capteur DHT22

Carte NodeMCU et capteur DHT22

Les broches D0 et Reset sont connectées entre elles afin de permettre à l'ESP8266 de se réveiller correctement après avoir été mis en deep-sleep.

Le DHT22 est connecté sur la broche D4 (GPIO02). Allez comprendre la numérotation des broches!

 

Concernant le stockage et la visualisation des données, j'ai cherché plusieurs solutions.

 

J'ai commencé par jeter un oeil à Thingspeak. C'est très simple à utiliser (un simple post HTTPS (voire HTTP mais c'est pas recommandé niveau sécu) et ça fournit une visualisation rudimentaire, extensible via différents moyens mais pas super bien documentée à mon goût (au choix via MathLab ou via HighCharts et un éditeur javascript/HTML intégré).

 

J'ai découvert il y a peu le PaaS IoT d'OVH (sur leur plateforme de "labs" Runabove).

Ils mettent à disposition un serveur OpenTDSB (protocole open-source de base de données temporelle). Il n'y a pas d'IHM de consultation, mais pour cela on peut utiliser Grafana, qu'il faut alors installer chez soi ou sur un cloud quelconque.

J'ai donc installé Grafana et j'y ai configuré un tableau de bord qui m'affiche des graphes et métriques de température et d'humidité de mes deux thermo-hygromètres connectés (un chez moi et un au boulot).

Voici ce que ça donne par exemple:

 

Le code source est disponible sur mon GitHub.

Il nécessite l'IDE Arduino avec la carte supplémentaire ESP8266.

 

La visualisation des données est faite avec Grafana, qui parle directement au PaaS IoT d'OVH avec le protocole OpenTSDB.

Grafana - Dashboard affichant les mesures de température et d'humidité

Grafana - Dashboard affichant les mesures de température et d'humidité

Repost 0
Published by breizhmakers - dans ESP8266
commenter cet article
8 avril 2016 5 08 /04 /avril /2016 16:45

Comme souvent je traînais sur un site de makers et je suis tombé sur la création d'un artiste, Lorenzo Bravi, qui est un séquenceur de percussions à base d'Arduino et Solénoïdes. L'idée étant ensuite de pouvoir changer facilement sur quoi les solénoïdes frappent afin d'en changer le son.

J'ai trouvé le concept sympa mais j'ai voulu faire quelque chose de plus versatile, pilotable via un vrai séquenceur MIDI (mais bien moins réussi niveau esthétique ;) )

 

J'ai commencé par faire un shield Arduino pour pouvoir commander les solénoïdes.

Version DYI bien sûr, c'est à dire sur une plaque à trous, au format shield Arduino.

6 MOSFET, quelques résistances, LED de contrôle et une poignée de connecteurs.

Comme souvent avec ce genre de montage, c'est pas très propre côté pistes, mais ça fonctionne.

MOSFET ShieldMOSFET Shield

MOSFET Shield

 

J'ai ensuite cherché un séquenceur MIDI pour Android, mais comme souvent dans le domaine de la musique, je n'ai trouvé mon bonheur que sur iPad. Le seul truc réellement utilisable par tous est Nord Beat 2, et gratuit en plus. Oui, le système est destiné à des enfants. J'aime bien faire des instruments d'éveil musical ludiques (voir le Mycophone par exemple).

 

Là s'est posé l'épineux problème de la connexion entre l'iPad et l'Arduino. Surtout que le Midi à la sauce Wifi Apple c'est comment dire....compliqué (doux euphémisme!...).

Après pas mal de recherches, j'ai opté pour l'excellent logiciel gratuit RTPMidi côté PC, que j'avais découvert en bricolant avec TouchDAW auparavant.

Donc après avoir installé RTPMidi et ce qui va avec (protocole "Bonjour"), et avoir lu attentivement la doc pas très claire, j'ai enfin vu mon iPad apparaître dans la liste des sessions Midi côté PC.

 

Restait à déterminer comment envoyer ces messages MIDI à l'Arduino.

C'est là qu'entre en jeu LoopBe1, un port midi virtuel et gratuit.

Ceci va en quelque sorte créer un câble MIDI virtuel entre les messages provenant de l'iPAD et...un programme Processing chargé de faire le relais entre le port MIDI virtuel et le port série sur lequel écoute l'Arduino.

J'ai opté pour un format de messsage entre Processing est l'Arduino qui n'est pas MIDI mais un format binaire ou chaque bit d'un octet correspond à un solénoïde à activer. Le tout transmis à 115200 bauds. C'est mon côté optimisateur fou :)

Le Sketch Processing transforme donc un message MIDI de type NoteOn en un bit à 1 et un NoteOff en un bit à 0.

Côté Arduino, un simple masque binaire permet de calculer l'état des sorties et d'utiliser les "fast I/O" pour les piloter.

Lors des premiers essais, des problèmes de latence sont vite apparus, le système était injouable dès que le tempo était un peu rapide.

La solution a été de passer par un réseau wifi pair-à-pair (mode ad-hoc) entre le PC et l'iPad. C'est une fonction wifi peu connue mais très pratique pour des échanges entre machines sans nécessiter un autre point d'accès.

Une fois le PC et l'iPad sur leur propre réseau wifi ad-hoc, la latence est retombée à quelques ms et le système a fonctionné à merveille.

 

Ma fille aime beaucoup et moi je m'amuse parfois à jouer de la basse avec ce type de boite à rythme.

J'ai ensuite cherché un séquenceur MIDI pour Android, mais comme souvent dans le domaine de la musique, je n'ai trouvé mon bonheur que sur iPad. Le seul truc réellement utilisable par tous est Nord Beat 2, et gratuit en plus. Oui, le système est destiné à des enfants. J'aime bien faire des instruments d'éveil musical ludiques (voir le Mycophone par exemple).

Là s'est posé l'épineux problème de la connexion entre l'iPad et l'Arduino. Surtout que le Midi à la sauce Wifi Appel c'est comment dire....compliqué (doux euphémisme!...).

Après pas mal de recherches, j'ai opté pour l'excellent logiciel gratuit RTPMidi côté PC, que j'avais découvert en bricolant avec TouchDAW auparavant.

Donc après avoir installé RTPMidi et ce qui va avec (protocole "Bonjour"), et avoir lu attentivement la doc pas très claire, j'ai enfin vu mon iPad apparaître dans la liste des sessions Midi côté PC.

Restait à déterminer comment envoyer ces messages MIDI à l'Arduino.

C'est là qu'entre en jeu LoopBe1, un port midi virtuel et gratuit.

Ceci va en quelque sorte créer un câble MIDI virtuel entre les messages provenant de l'iPAD et...un programme Processing chargé de faire le relais entre le port MIDI virtuel et le port série sur lequel écoute l'Arduino.

J'ai opté pour un format de messsage entre Processing est l'Arduino qui n'est pas MIDI mais un format binaire ou chaque bit d'un octet correspond à un solénoïde à activer. Le tout transmis à 115200 bauds. C'est mon côté optimisateur fou :)

Le Sketch Processing transforme donc un message MIDI de type NoteOn en un bit à 1 et un NoteOff en un bit à 0.

Côté Arduino, un simple masque binaire permet de calculer l'état des sorties et d'utiliser les "fast I/O" pour les piloter.

Lors des premiers essais, des problèmes de latence sont vite apparus, le système était injouable dès que le tempo était un peu rapide.

La solution a été de passer par un réseau wifi pair-à-pair (mode ad-hoc) entre le PC et l'iPad. C'est une fonction wifi peu connue mais très pratique pour des échanges entre machines sans nécessiter un autre point d'accès.

Une fois le PC et l'iPad sur leur propre réseau wifi ad-hoc, la latence est retombée à quelques ms et le système a fonctionné à merveille.

Ma fille aime beaucoup et moi je m'amuse parfois à jouer de la basse avec ce type de boite à rythme.

Démo avec ma fille

 

Le code source des sketches Arduino et Processing est disponible sur GitHub.

Repost 0
Published by breizhmakers - dans arduino
commenter cet article
24 mars 2016 4 24 /03 /mars /2016 21:22

On trouve peu d'exemples d'utilisation de l'Arduino/Genuino MKR1000.

Ci-dessous un exemple de sketch qui envoie les valeurs lues sur une entrée analogique vers un channel ThingSpeak, issus des exemples de la librairie Wifi101 ainsi que d'exemples d'utilisation de l'API ThingSpeak trouvés en ligne.

 

L'entrée analogique est configurée en 1V max / 12bits de résolution. 

Vous devez spécifier votre clé d'API ThingSpeak ainsi que votre SSID et mot de passe wifi.

 

J'ai utilisé ce code pour lire les valeurs issues d'un sonomètre et les poster sur mon channel Thingspeak.

#include <SPI.h>
#include <WiFi101.h>
#include <stdarg.h>


//analog input pin
#define ANALOG_PIN A1


//thinkgspeak API KEY
#define API_KEY "YOUR_WRITE_API_KEY"


#define WIFI_ENABLE
#define WIFI_NETWORK_NAME "your_wifi_ssid"
#define WIFI_PASSWORD "your_wifi_password"    


#define SERVER "api.thingspeak.com"  
#define SLEEP_TIME 15000

int status = WL_IDLE_STATUS;
char buffer[70];
WiFiSSLClient client;


void setup() {
  Serial.begin(9600);
  //set 12 bit analog resolution
  analogReadResolution(12);
  //set 1V analog reference
  analogReference(AR_INTERNAL1V0);


#ifdef WIFI_ENABLE
  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(WIFI_NETWORK_NAME);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(WIFI_NETWORK_NAME, WIFI_PASSWORD);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWifiStatus();
#endif
}


//main loop
void loop() {
  int sensorValue = analogRead(ANALOG_PIN);
 

#ifdef WIFI_ENABLE
  //send data to thingSpeak
  sendData(sensorValue);
  
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }
    delay(SLEEP_TIME);  
#else
  Serial.println(sensorValue);
  delay(SLEEP_TIME/50);
#endif
}


void sendData(int data){
  if (client.connect(SERVER, 443)) {
    Serial.print("connected to server to send data :");
    Serial.println(data);
    // Make a HTTP request:
    sprintf(buffer,"GET /update?api_key=%s&field1=%d HTTP/1.1",API_KEY,data); 
    Serial.println(buffer);
    client.println(buffer);
    client.print("Host: ");
    client.println(SERVER);
    client.println("Connection: close");
    client.println();
    Serial.println("data sent");
  }else{
    Serial.println("connection error");
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());


  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);


  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
Repost 0
Published by breizhmakers - dans arduino mkr1000
commenter cet article
18 décembre 2015 5 18 /12 /décembre /2015 20:51

J'aime terminer un projet, et celui-là est vraiment sympa puisqu'il s'agit d'animer un tableau de Je Peins Des Aliens.
J'ai encore plein d'idées pour donner vie à ces créatures

Voilà ce que ça donne:

Repost 0
Published by breizhmakers - dans arduino
commenter cet article