Lampadaire Wifi / domotique

Discussions autour des autres moyens de création : : découpe vinyle, découpe à fil chaud ...
chris34
Messages : 10
Enregistré le : sam. 23 janv. 2016 19:21
Adhérent Labsud : Adhérent

Lampadaire Wifi / domotique

Messagepar chris34 » jeu. 13 oct. 2016 14:35

Et hop, petit bricolage d'autome : un lampadaire led / wifi / domotique. On s'y jette ?
https://youtu.be/pJBcHCMPtbs
J'ai acheté un ruban LEDs "intelligentes" WS2812B, sans but précis, juste par curiosité de ces leds dites "intelligentes".
Ce ruban de 5m comprend 300 noeuds de 3 leds RVB adressables individuellement, on peut donc allumer chaque plot individuellement de 0 à 255 pour chaque couleur. Le ruban est recoupable facilement avec une simple paire de ciseaux.
Alors comment ça marche ? Il faut 3 fils, 0v +5v et un bus. On envoie une trame sur le bus avec des instructions RVB pour noeud1, noeud2, noeud3, etc.... quand un noeud recoit la trame avec une instruction pour noeud1, il considère que c'est pour lui, allume ses leds en conséquence et retransmet la trame au noeud suivant, en supprimant au passage les instructions pour noeud1 (qui ont été traitées), noeud2 fera de même etc...
Aucune "intelligence" donc mais un procédé assez malin et un exploit technique malgré tout, il y a quand même 300 cpus embarqués qui collaborent pour faire le job !
J'ai d'abord vérifié que le ruban fonctionnait une fois connecté à un ESP8266. Après quelques ratés, bonne surprise, ça marche et c'est très rapide !
Alors quoi faire avec ça ? un simple éclairage d'ambiance sous un meuble... du gachis, il faut un truc matriciel qui puisse afficher des choses complexes. Une matrice carrée bof, c'est quelconque. Pourquoi pas un lampadaire qui serait capable d'éclairer et d'afficher quelques informations sous forme de matrice. L'inconvénient c'est que quelque soit le point de vue, on perd visuellement la moitié de la matrice. Mais c'est aussi un avantage, quelque soit le point de vue on peut lire.
Le problème de l'alimentation : De fait, on se retrouve avec 300 noeuds de 3 leds (RVB). Comptons 20mA par led. Donc potentiellement 18A sous 5v pour allumer l'ensemble en blanc à pleine puissance ! En pratique, mes essais confirment qu'une alim de 8A suffit. On peut de toutes façons régler la puissance pour éviter que le milieu du ruban ne devienne jaunâtre ou même rouge. Avec 8A je ne perçois une dégradation qu'au dessus d'une intensité de 200 (sur 255 possible), ce qui suffit largement à arracher les yeux et à éclairer une pièce de 15m². Sur la vidéo j'ai réglé à 30 pour éviter de cramer le capteur de mon téléphone. De toutes façons les alims > 8A sont hors de prix et hors gabarit pour ce que je veux faire.
Avec juste le port USB connecté à mon PC ça fonctionne, on ne peut pas tout allumer en blanc, mais les 3 couleurs primaires fonctionnent individuellement à faible puissance.

Matériel :
Un ruban de 5m / 300leds WS2812B (environ 30€ sur ebay)
Une alim format allongé (spécial led) 5v / 8A. Vérifier que sa taille est compatible avec le tube ! (environ 30€ sur amazon)
Un ESP8266-12 wifi (environ 10€ ebay), surement possible avec un Wemos à 3€
Un chute de médium 30x30 pour le socle
Un cable micro-usb (facultatif, pour faire les mises-à-jour logiciel sans tout démonter)
5m de câble 3x1mm (magasin de bricolage)
Un tube PVC 200 x 68 et quelques raccords (environ 7€ dans tous les magasins de bricolage)

Montage :
Ruban led : Il faut enrouler le ruban led adhésif autour du tube. Mais bien entendu, le pourtour du tube de 68 ne correspond pas pile au leds qui font chacune 16mm de long (60 leds / mètre). J'ai donc grossi artificiellement le diamètre du tube en enroulant du papier adhésif.
Comme vous pouvez voir sur la vidéo et les photos, les leds ne sont pas impeccablement alignées, surtout sur les premiers tours. Difficile de trouver le bon nombre de tour de scotch pour coller le ruban led et avec les leds parfaitement alignées.
Socle : Un raccord 45° (je n'ai trouvé que ça en 68) découpé à la scie à métaux et poncé, collé au milieu d'une planche carrée. Le tube s'emmanche dedans. Percer le centre du socle assez gros pour passer le fil secteur et la prise usb. Faire une saignée sur le dessous pour que les câbles passent sans que le socle ne soit bancal. Vous pouvez aussi creuser un emplacement pour la prise USB qui ne sert que pour la mise à jour et pourra s'intégrer sous le socle pour ne laisser sortir que la prise 220v.
En haut du tube j'ai ajouté un morceau de raccord pour la finition, le prévoir avant de commencer à enrouler le ruban de leds.
Raccordements :
Le ruban est alimenté au 2 bouts ce qui peut paraître curieux, mais quand on a calculé les puissances dissipées on comprend qu'en alimentant qu'à une extrémité, le ruban de 5m ne s'allumera jamais en entier. Il faut donc percer le tube en haut et en bas de l'enroulement pour descendre un câble d'assez grosse section à l'intérieur.
Il faut aussi descendre le fil du bus (le câble de terre fera l'affaire). Attention le bus à un sens. J'ai pas fait gaffe, l'entrée du bus est en bas de l'enroulement.
Peu importe car on peut corriger en bidouillant le soft. Si vous voulez reprendre mon code tel quel, faites comme moi !
Raccorder les deux + du ruban, le Vin de l'ESP et le + de l'alim ensemble
Raccorder les deux - du ruban, le GND de l'ESP et le - de l'alim ensemble
Raccorder le bus du ruban au 5 de l'ESP
Faites descendre les 2 câbles dans le tube jusqu'au socle.
Brancher le câble USB sur l'ESP en traversant le socle.
Passer le câble 220v avant de raccorder les câbles à l'alim.
Glissez soigneusement l'ESP, l'alim et les câbles dans le tube.

Logiciel :
Comme l'ESP comporte un module wifi, le principe est de le configurer en mini serveur web de manière à adresser les différentes fonctions en appelant une URL à partir de l'extérieur. Pensez à configurer le bail DHCP de votre boxe internet afin que l'ESP prenne toujours la même adresse IP.
Le code est fait en C++ via l'interface de programmation Arduino, simple et rapide. Je ne rentre pas dans le détail pour la gestion des librairies, téléchargez et installez ESP8266WiFi / Adafruit_NeoPixel / TimeLib / WiFiUdp avant de compiler le code et de l'envoyer dans l'ESP via USB.
Programmation : Le plus pénible est de créer les matrices pour chaque caractère à afficher en effet j'ai 23 tours de 13 leds ch acun mais si on veut pouvoir lire il faut des caractères de 23x6. Je n'ai fait que les chiffres de 0 à 9, les ":" et l'espace. J'ai utilisé Excel pour dessiner les caractères et générer une liste de booléens correspondant.
Si vous vous y collez pour l'alphabet majuscule / minuscule, partagez avec nous !
Une fois chaque caractère en matrice, il faut adresser le ruban, qui lui est linéaire (leds 1 à 300), ça se complique bigrement au niveau soft !
Surtout quand on veut les faire défiler comme pour l'heure sur la vidéo. J'ai décidé de mettre tout ce qui devait être affiché dans une grande matrice (avec des blancs avant et après pour un défilement fluide). Ensuite il faut 3 boucles imbriquées (x, y et le décallage) pour afficher la matrice 13x23 et la faire scroller. Inutile d'effacer à chaque fois, ca sintillerait et ça n'apporte rien car toutes les leds sont mises à jour. C'est là qu'on voit que c'est super rapide, j'ai temporisé sinon on ne peut pas lire.
En fait on prépare la trame dans le soft, et quand on l'envoie les 300 leds s'allument instantanément dans la couleur demandée. Le déroulement de l'heure c'est 42 fois l'adressage de 300 leds, 12600 adressages en 3 secondes sans temporisa tion. Impressionnant.
Après il y a les anneaux et les secteurs qui dépendent de la matrice mais qui sont nettement plus simples niveau programmation.
Le reste des effets sont repris des exemples que j'ai trouvé sur le net.
Heure : Au départ j'ai bricolé un bout de code php sur mon serveur jeedom pour pouvoir passer l'heure à l'ESP. Compliqué, depuis Jeedom on appelle le code php qui appelle l'ESP. Heureusement, il y a une librairie time et même une synchronisation NTP qui permet à l'ESP de rester pile à l'heure malgré l'absence d'horloge matérielle. On pourrait même faire défiler la date.
Jeedom : Quand on en est là, il suffit de faire un script avec des boutons et un appel http pour activer telle ou telle fonction, à vous d'ajouter les vôtres. Il y a un retour d'état qui peut servir pour connaître la fonction en cours d'exécution, 0 si éteint.
Une fois fait vous pourrez activer chaque fonction à partir de vos scenarios. Je n'ai pas fait de plugin parce que c'est évolutif, du coup il faudrait le mettre à jour à chaque ajout de fonctionnalité.
Sur la vidéo je déclenche la démo à partir d'une télécommande zwave.
Problème :
Pour être honnête je m'y suis repris à 3 fois pour faire une vidéo "propre". Il semble que quand on sollicite trop le ruban il arrive qu'il bug plus ou moins. Parfois il semble qu'un noeud arrête de transmettre la trame aux noeuds suivants. Ça peut même parfois empêcher d'éteindre le ruban. J'ignore si ca le fait sur tous ou uniquement sur le miens. Je l'ai quand même maltraité (branchement du bus à l'envers...). Si on sépare les opérations de quelques secondes / minutes il n'y a pas de problème, c'est fiable à 100%.

Évolutions :
Il me reste les finitions hardware. Un coup de papier de verre et peinture sur le tube, le socle et le bouchon en haut. Il faut que je me débrouille pour que le tube continue à être amovible pour laisser l'accès à l'électronique.
Côté électronique on peut par exemple facilement ajouter un capteur de température sur l'ESP qui remonterait des valeurs à Jeedom. Pourquoi pas un détecteur de présence à ultra son en perçant le tube à mi-hauteur ?
En matière de soft c'est encore plus vaste. On peut imaginer de faire défiler une météo simplifiée avec la température prévue et un logo pour peu qu'on se donne la peine de mettre les logos en matrice. Faire clignoter le lampadaire quand on a un mail ou faire défiler un panneau triangulaire quand il y a un bouchon sur le trajet du boulot devient un jeu d'enfant.
J'ai un algorithme qui passe du jaune au bleu en passant par le rouge en 30mn, je l'exécute à l'heure du couché du soleil, c'est assez déco et fun même si les jours raccourcissent. J'ai la même chose à l'inverse (du bleu au jaune) au levé du soleil.
A vous de jouer maintenant, j'attends vos idées et vos réalisations avec impatience !
Quelques photos en vrac :
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image

Le code (bien sale comme il se doit pour un proto) :

Code : Tout sélectionner

#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <TimeLib.h>
#include <WiFiUdp.h>

#define DEBUG 0

int etat = 0;
int nbPixels = 300;
int intensite = 30;
int delai = 0;
const char ssid[] = "lavieestbelle";
const char pass[] = "pass";

unsigned int localPort = 8888; 
static const char ntpServer[] = "us.pool.ntp.org";
const int timeZone = 2;     
//time_t prevDisplay = 0;
//time_t getNtpTime();
const int NTP_PACKET_SIZE = 48;
byte packetBuffer[NTP_PACKET_SIZE];

Adafruit_NeoPixel strip = Adafruit_NeoPixel(nbPixels, 5, NEO_GRB + NEO_KHZ800);

bool seg[10][300] = { 
  {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,},
  {0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,},
  {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,},
  {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0,0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,},
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,},
  {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0,0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,},
  {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,},
  {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,},
  {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,},
  {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0,0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,}
}; 

bool seg1[12][138] = { 
  {0, 0, 1, 1, 0, 0,0, 1, 1, 1, 1, 0,1, 1, 1, 1, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 1, 1, 1, 1,0, 1, 1, 1, 1, 0,0, 0, 1, 1, 0, 0},
  {0, 0, 1, 1, 1, 1,0, 0, 1, 1, 1, 1,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 0,0, 0, 1, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 0, 1, 0},
  {1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 0, 1, 1, 0, 0,0, 0, 1, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 1,0, 0, 0, 0, 1, 1,0, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 1, 1, 1, 1,0, 1, 1, 1, 1, 0,0, 0, 1, 1, 0, 0},
  {0, 1, 1, 1, 0, 0,1, 1, 1, 1, 1, 0,1, 1, 0, 1, 1, 1,1, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 1, 1, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,1, 0, 0, 0, 1, 1,1, 1, 0, 1, 1, 1,1, 1, 1, 1, 1, 0,0, 1, 1, 1, 0, 0},
  {0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,1, 1, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 0, 1, 1, 0,1, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 0,0, 0, 1, 1, 1, 0,0, 0, 1, 1, 1, 0,0, 0, 0, 1, 1, 0},
  {0, 1, 1, 1, 0, 0,1, 1, 1, 1, 1, 0,1, 1, 0, 1, 1, 1,1, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 1, 1, 0,0, 0, 1, 1, 1, 0,0, 1, 1, 1, 0, 0,1, 1, 1, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1},
  {0, 1, 1, 1, 0, 0,1, 1, 1, 1, 1, 0,1, 1, 0, 1, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 1, 1, 1,1, 1, 1, 1, 1, 0,1, 1, 1, 1, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 1, 1, 1, 0,0, 1, 1, 1, 0, 0},
  {1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,1, 1, 0, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 1, 1, 0, 0, 0,0, 0, 1, 1, 0, 0,0, 0, 1, 1, 0, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 0,0, 0, 0, 1, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1},
  {0, 0, 1, 1, 0, 0,0, 1, 1, 1, 1, 0,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,0, 1, 1, 1, 1, 0,0, 1, 1, 1, 1, 0,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,0, 1, 1, 1, 1, 0,0, 0, 1, 1, 0, 0},
  {0, 1, 1, 1, 0, 0,1, 1, 1, 1, 1, 0,1, 1, 0, 1, 1, 1,1, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 0, 0, 1, 1,0, 0, 1, 1, 1, 1,0, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 0, 0, 1, 1,1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 0,0, 1, 1, 1, 0, 0},
  {0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 1, 1, 1, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0}
}; 

WiFiServer server(80);
WiFiUDP Udp;

void setup() {
  strip.begin();
  neoShow();
 
  Serial.begin(115200);
  //pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
 
  Serial.println("");
  Serial.print("Connexion a ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
 
  uint8_t ligne =1;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    neoCercle(0, 0, intensite, ligne, 800);
    ligne++;
  }
  Serial.println(".");
  Serial.print("L'adresse IP assignee par DHCP est ");
  Serial.println(WiFi.localIP());
  neoEteint();
  for (int i=0; i<4; i++){
    neoCercle(0, intensite, 0, ligne, 300);
    //neoAllume(0, intensite, 0, 2000);
    neoAllume(0, 0, 0, 300);
 }

  server.begin();
  Serial.println("Serveur ok");
  Serial.print("URL: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
  setSyncInterval(60);
 
  Serial.println(FormatHeure().substring(0,5));
}

void loop() {
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  } 
  String req = client.readStringUntil('\r');
  Serial.print("req:");
  Serial.println(req);
  String message = req.substring(req.indexOf("/")+7, req.indexOf("/")+12);
  String request = req.substring(req.indexOf("/")+1, req.indexOf("/")+7);
  Serial.print("request:");
  Serial.println(request);
  Serial.print("message:");
  Serial.println(message);
  client.flush();

  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("");

  if (request.substring(0,3) == "COL") {
    Serial.print("color:");

  } else if (request.substring(0,3) == "INT") {
    String intens=request.substring(3,request.indexOf(" "));
    Serial.print("intensite:");
    Serial.println(intens);
    intensite=intens.toInt();
   
  } else if (request == "LED_ON"){
    digitalWrite(LED_BUILTIN, LOW);
  } else if (request == "LED_OF"){
    digitalWrite(LED_BUILTIN, HIGH);
     
  } else if (request == "ALL_WH"){
    neoAllume (intensite, intensite, intensite, 0);
    etat = 11;
    Serial.println(etat);
  } else if (request == "ALL_RO"){
    neoAllume (intensite, 0, 0, 0);
    etat = 12;
  } else if (request == "ALL_VE"){
    neoAllume (0, intensite, 0, 0);
    etat = 13;
  } else if (request == "ALL_BL"){
    neoAllume (0, 0, intensite, 0);
    etat = 14;
     
  } else if (request == "WIP_WH"){
    colorWipe(intensite, intensite, intensite, 100);
    etat = 21;
  } else if (request == "WIP_RO"){
    colorWipe(intensite, 0, 0, 100);
    etat = 22;
  } else if (request == "WIP_VE"){
    colorWipe(0, intensite, 0, 100);
    etat = 23;
  } else if (request == "WIP_BL"){
    colorWipe(0, 0, intensite, 100);
    etat = 24;
     
  } else if (request == "THE_WH"){
    theaterChase(intensite, intensite, intensite, 0);
    etat = 31;
  } else if (request == "THE_RO"){
    theaterChase(intensite, 0, 0, 0);
    etat = 32;
  } else if (request == "THE_VE"){
    theaterChase(0, intensite, 0, 0);
    etat = 33;
  } else if (request == "THE_BL"){
    theaterChase(0, 0, intensite, 0);
    etat = 34;
 
  } else if (request == "DIV_RB"){
    rainbow(2);
    etat = 41;
  } else if (request == "DIV_RC"){
    rainbowCycle(2);
    etat = 42;
  } else if (request == "DIV_CR"){
    theaterChaseRainbow(5);
    etat = 43;

  } else if (request == "DIV_TS"){
    neoDemo();
    //neoScroll(0, 0, intensite, 0, 0, 0, message, 100);
    //neoMessage(intensite, 0, 0, 0, 0, 0, "9876543210", 1000);
    //neoCylindre(300);
    //neoSegment(30);
    etat = 51;
   
  } else if (request == "ETEINT"){
      neoEteint();
      etat = 0;
  } else if (request == "ETATNP"){
  }

  client.println(etat);
  Serial.println(etat);

  delay(1);
  Serial.println("Client disonnected");
  Serial.println("");
}

void neoAllume(uint8_t R, uint8_t V, uint8_t B, int delai){
  for(int i=0; i<nbPixels; i++){
    strip.setPixelColor(i, strip.Color(R, V, B));
  }
  neoShow();
  if (delai>0){
    delay(delai);
    neoEteint();
  }
}

void neoEteint(){
  for(int i=0;i<nbPixels;i++){
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  neoShow();
}

void neoShow(){
  if (DEBUG == 0) {
    strip.show();
    strip.show();
    strip.show();
  }
}

void neoDemo(){
    Serial.println("1");
    for (int i=9; i>-1; i--) {
      int v=intensite*(i+1)/10;
      int r=intensite-v;
      neoMessage(r, v, 0, 0, 0, 0, i, 1000);
      Serial.print("R");Serial.println(v);
      Serial.print("V");Serial.println(r);
    }
   
    //delay(3000);
    Serial.println("2");
    neoScroll(0, 0, intensite, intensite, intensite, intensite, FormatHeure().substring(0,5), 100);
    Serial.println("3");
    neoCylindre(intensite, 0, 0, 1, 100);
    neoCylindre(intensite, 0, 0, 0, 100);
    neoEteint();
   
    delay(2000); Serial.println("4");
    neoSegment(intensite, intensite, 0, 1, 150);
    neoSegment(intensite, intensite, 0, 0, 150);
    neoEteint();
    delay(5000); Serial.println("5");
    neoAllume (intensite, intensite, 0, 3000);
    neoAllume (0, intensite, intensite, 3000);
    neoAllume (intensite, 0, intensite, 3000);
    delay(5000); Serial.println("6");
    theaterChase(intensite, 0, intensite, 50);
    delay(5000); Serial.println("7");
    colorWipe(intensite, 0, intensite, 50);
    delay(5000); Serial.println("8");
    rainbow(2);
    delay(5000); Serial.println("9");
    rainbowCycle(2);

    delay(5000); Serial.println("10");
    theaterChaseRainbow(2);
    delay(5000); Serial.println("11");
    neoEteint();
    neoScroll(intensite, intensite, intensite, 0, 0, 0, FormatHeure().substring(0,5), 10);
   
    for (int i=0; i<10; i++) {
      int v=intensite*(i+1)/10;
      int r=intensite-v;
      neoMessage(r, v, 0, 0, 0, 0, i, 1000);
      Serial.print("R");Serial.println(v);
      Serial.print("V");Serial.println(r);
    }
}



void neoMessageOld(uint8_t r1, uint8_t v1, uint8_t b1, uint8_t r2, uint8_t v2, uint8_t b2, String msg, int delai){
  for (int i=0; i<msg.length(); i++) {
    String s1 = msg.substring(i, i+1);
    Serial.println(s1);
    int s2 = s1.toInt();
    for(int j=1; j<299; j++){
      if (seg[s2][j] == 1) {
        strip.setPixelColor(j, strip.Color(r1, v1, b1));
      } else {
        strip.setPixelColor(j, strip.Color(r2, v2, b2));
      }
    }
    neoShow();
    delay(delai);
  }
  neoEteint();
  etat = 0;
}

void neoMessage(uint8_t r1, uint8_t v1, uint8_t b1, uint8_t r2, uint8_t v2, uint8_t b2, int msg, int delai){
  bool matrice[33][23];
  memset(matrice,0,sizeof(matrice));

  //for (int i=0; i<msg.length(); i++) {
    //String s1 = msg.substring(i, i+1);
    //Serial.println(s1);
    int s2 = msg;
    //if (s1 == ":") {s2=10;}
    //if (s1 == " ") {s2=11;}
    for(int j=0; j<138; j++){
      matrice[3+(j%6)][int(j/6)]=seg1[s2][j];
      //if (j%6 == 0) {Serial.println((int(j/6)));}
      //Serial.print(seg1[s2][j]);
    }
  //}
  //Serial.println();
  //Serial.println("done");
  for (int i=0; i<33; i++) {
    for(int j=0; j<23; j++){
      //Serial.print(matrice[i][j]);
    }
    //Serial.println();
  }
 
  //Serial.println("done 2");
 
  //for (int i=0; i<msg.length()*7+13; i++) {
    for(int k=0; k<13; k++) {
      for(int j=0; j<23; j++){
        //Serial.print(matrice[k][j]);
        //Serial.print(j*13+(k-i)+1);
        //Serial.print(" ");
        //if (j%23 == 0) {Serial.println("");}
        if (matrice[k][j] == 1) {
          strip.setPixelColor(j*13+k+1, strip.Color(r1, v1, b1));
        } else {
          strip.setPixelColor(j*13+k+1, strip.Color(r2, v2, b2));
        }
      }
      //Serial.println();
    }
    neoShow();
    //delay(delai);
    //Serial.println(i);
  //}
  delay(delai);
  //neoEteint();
  etat = 0;
}

void neoScroll(uint8_t r1, uint8_t v1, uint8_t b1, uint8_t r2, uint8_t v2, uint8_t b2, String msg, int delai){
  bool matrice[msg.length()*7+26][23];
  memset(matrice,0,sizeof(matrice));

  for (int i=0; i<msg.length(); i++) {
    String s1 = msg.substring(i, i+1);
    Serial.println(s1);
    int s2 = s1.toInt();
    if (s1 == ":") {s2=10;}
    if (s1 == " ") {s2=11;}
    for(int j=0; j<138; j++){
      matrice[i*7+13+(j%6)][int(j/6)]=seg1[s2][j];
      if (j%6 == 0) {Serial.println((int(j/6)));}
      Serial.print(seg1[s2][j]);
    }
  }
  Serial.println();
  Serial.println("done");
  for (int i=0; i<msg.length()*7+26; i++) {
    for(int j=0; j<23; j++){
      Serial.print(matrice[i][j]);
    }
    Serial.println();
  }
 
  Serial.println("done 2");
 
  for (int i=0; i<msg.length()*7+13; i++) {
    for(int k=i; k<i+13; k++) {
      for(int j=0; j<23; j++){
        Serial.print(matrice[k][j]);
        //Serial.print(j*13+(k-i)+1);
        //Serial.print(" ");
        if (j%23 == 0) {Serial.println("");}
        if (matrice[k][j] == 1) {
          strip.setPixelColor(j*13+(k-i)+1, strip.Color(r1, v1, b1));
        } else {
          strip.setPixelColor(j*13+(k-i)+1, strip.Color(r2, v2, b2));
        }
      }
      Serial.println();
    }
    neoShow();
    delay(delai);
    Serial.println(i);
  }
  delay(1000);
  neoEteint();
  etat = 0;
}

void neoCercle(uint8_t R, uint8_t V, uint8_t B, uint8_t ligne, int delai){
  for(int i=0; i<13; i++){
    strip.setPixelColor((ligne*13)+i, strip.Color(R, V, B));
  }
  neoShow();
  if (delai>0){
    delay(delai);
    neoEteint();
  }
}

void neoCylindre(uint8_t R, uint8_t V, uint8_t B, int sens, int delai){
  int b1, b2, inc;
  if (sens==1) {
    b1=-1; b2=23; inc=1;
  } else {
    b1=23; b2=-1; inc=-1;
  }
  for (int i=b1; i!=b2; i=i+inc) {
    Serial.println(i);
    for(int j=0; j<13; j++){
      strip.setPixelColor((i*13)+j, strip.Color(R, V, B));
    }
    neoShow();
    delay(delai);
    for(int j=0; j<13; j++){
      strip.setPixelColor((i*13)+j, strip.Color(0, 0, 0));
    }
    neoShow();
  }
}

void neoSegment(uint8_t R, uint8_t V, uint8_t B, int sens, int delai){
  int b1, b2, inc;
  if (sens==1) {
    b1=0; b2=13; inc=1;
  } else {
    b1=13; b2=0; inc=-1;
  }
  for (int i=b1; i!=b2; i=i+inc) {
    for(int j=1; j<23; j++){
      strip.setPixelColor((j*13)+i, strip.Color(R, V, B));
    }
    neoShow();
    delay(delai);
    for(int j=0; j<23; j++){
      strip.setPixelColor((j*13)+i, strip.Color(0, 0, 0));
    }
    neoShow();
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint8_t R, uint8_t V, uint8_t B, int delai) {
  for(uint16_t i=0; i<nbPixels; i++) {
    strip.setPixelColor(i, strip.Color(R, V, B));
    neoShow();
    delay(delai);
  }
}

void rainbow(int delai) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    neoShow();
    delay(delai);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(int delai) {
  for(uint16_t j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(uint16_t i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    neoShow();
    delay(delai);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint8_t R, uint8_t V, uint8_t B, int delai) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, strip.Color(R, V, B));    //turn every third pixel on
      }
      neoShow();

      delay(delai);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(int delai) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      neoShow();

      delay(delai);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85){
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170){
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

time_t getNtpTime(){
  IPAddress ntpServerIP; // NTP server's ip address
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  // get a random server from the pool
  WiFi.hostByName(ntpServer, ntpServerIP);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

void sendNTPpacket(IPAddress &address){
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}
String doubleDigits(int digits, boolean format){
  String dD;
  if (digits < 10) if (format == 0) dD = " "; else dD = "0";
  dD += String(digits);
  return dD;
}

String FormatHeure() {
  String dt = String(doubleDigits(hour(), 0)) + ":" + String(doubleDigits(minute(), 1)) + ":" + String(doubleDigits(second(), 1));
  return dt;
}

String FormatDate() {
  String dow[7] = {"Dimanche ", "Lundi ", "Mardi ", "Mercredi ", "Jeudi ", "Vendredi ", "Samedi "};
  String moy[12] = {" janvier ", " février ", " mars ", " avril ", " mai ", " juin ", " juillet ", " août", " septembre ", " octobre ", " novembre ", " décembre "};
  String dt = dow[weekday()-1];
  dt += day();
  dt += moy[month()-1];
  return dt;




Strophe
Messages : 52
Enregistré le : dim. 12 oct. 2014 14:27
Adhérent Labsud : Adhérent

Re: Lampadaire Wifi / domotique

Messagepar Strophe » jeu. 13 oct. 2016 14:49

Whaouuu! Merci de partager ça, c'est inspirant ! Bel automne...

Avatar de l’utilisateur
jpcivade
Messages : 118
Enregistré le : dim. 10 mars 2013 11:19
Adhérent Labsud : Adhérent
Localisation : Montpellier
Contact :

Re: Lampadaire Wifi / domotique

Messagepar jpcivade » jeu. 13 oct. 2016 16:38

Bravo pour cette belle réalisation....
Jean-Philippe CIVADE
Fondateur du Fablab Labsud
Blog Maker : http://www.civade.com

Avatar de l’utilisateur
frafa
Messages : 56
Enregistré le : dim. 17 mars 2013 10:51
Adhérent Labsud : Adhérent
Localisation : Montpellier
Contact :

Re: Lampadaire Wifi / domotique

Messagepar frafa » jeu. 13 oct. 2016 16:46

Superbe! merci d'avoir partagé

monkey3d
Messages : 40
Enregistré le : jeu. 16 oct. 2014 12:31
Adhérent Labsud : Adhérent

Re: Lampadaire Wifi / domotique

Messagepar monkey3d » jeu. 13 oct. 2016 16:53

Félicitations pour l'idée, la mise en oeuvre réussie et le partage des informations de réalisation.
Claude

Avatar de l’utilisateur
Stivus
Messages : 22
Enregistré le : mer. 22 oct. 2014 22:54
Adhérent Labsud : Adhérent

Re: Lampadaire Wifi / domotique

Messagepar Stivus » jeu. 13 oct. 2016 21:37

Vraiment bien, ça donne des idées !
Merci pour le partage

chris34
Messages : 10
Enregistré le : sam. 23 janv. 2016 19:21
Adhérent Labsud : Adhérent

Re: Lampadaire Wifi / domotique

Messagepar chris34 » dim. 13 nov. 2016 19:32

Nouvelle vidéo avec de nouveaux effets et un cache plastique qui masque pas mal les leds ;)
https://youtu.be/CWE71laoYQA

chris34
Messages : 10
Enregistré le : sam. 23 janv. 2016 19:21
Adhérent Labsud : Adhérent

Re: Lampadaire Wifi / domotique

Messagepar chris34 » lun. 19 mars 2018 14:35

Voici la V2 de mon lampadaire à LED.
Démo :
[youtube]https://youtu.be/9TxUNcG-ITk[/youtube]
Les photos sont à la fin de la vidéo.
La V1 avait quand même beaucoup de défauts :
· Les leds étaient mal alignées, à cause du ruban de LEDs "enroulé" autour du tube.
· Pas d'abat-jour le ruban de leds apparent n'est pas esthétique du tout.
· La puissance n'est pas transmise correctement aux leds du milieu du ruban, même en alimentant à chaque bout.
· Pas de finitions, impossible de convaincre qui que ce soit de mettre ca dans son salon !

J'ai donc repris le concept en essayant de faire plus propre.

Hardware :
On a toujours comme base le tube d'évacuation en PVC de 2000x68.
Cette fois les rubans de leds sont positionnés verticalement ce qui permet de les aligner.
D'autant que le vrai problème d'alignement arrive quand on tombe sur une soudure (toute les 30 leds le ruban est soudé à la main donc les 2 leds soudées n'ont pas un écartement standard).
Ca tombe bien j'ai 15 leds en hauteur.
Ensuite il y a le problème de la circonférence du tube qui ne correspond pas avec la largeur du ruban (10mm), j'ai donc imprimé 2 "manchons" qui permettent d'obtenir 22cm de tour.
On se retrouve avec une matrice de 22x15 soit 330 leds.
J'avais remarqué dans la v1 que les leds du milieu recevaient moins de puissance qu'aux extrémités. Normal puisque les rubans transmettent l'alimentation par des pistes flexibles très fines.
Pour passer la puissance j'ai opté pour du fil électrique rigide 1.5 utilisé dans le bâtiment. Après l'avoir dénudé on peut le cercler pour faire un "bus" positif en haut et négatif en bas. A souder c'est un peu galère parce que chaque soudure fait fonde la précédente. Et pour souder du 1.5² sur une piste de ruban il vaut mieux s'y prendre avant l'apéro :) Vous pouvez voir que ce n'est pas nickel mais qu'importe, ce ne sera pas visible. C'est quand même un miracle que ça ait fonctionné du premier coup vu la tronche de mes soudures !
Ensuite il reste à souder le bus. Attention de coller les bandeaux de leds dans le bon sens afin que chaque borne "out" soit en face de la borne "in" du suivant.
Côté alimentation je suis resté sur 5v / 8A. D'abord pour sa forme qui rentre dans le tube. Et puis j'ai fait des essais avec 2 alimentations en // et en allumant tout je ne tire pas plus de puissance qu'avec une seule alim : 9,2A.
Pourtant on a 990 leds (R V et B par plot). Même à 15mA par led on devrait pouvoir tirer presque 15A.
Relativisons, on a coutume de dire que les leds éclairent 10 fois plus à puissance égale, j'ai donc l'équivalent de 460w avec cette alim, et je peux vous certifier que ça éclaire très fort ! Sur la vidéo on est à 40 de puissance sur 255 possible, je voulais éviter de cramer le capteur de mon appareil photo.
Côté finition j'ai imprimé un "abat-jour" blanc de 24cm de haut (c'est la limite Z de mon imprimante) et 0,6mm d'épaisseur.
Les 24cm c'est un vrai coup de bol je n'avais pas eu cette idée au départ. Vous pouvez voir que c'est quand même un poil juste, ça aurait été plus joli avec 2cm de plus.
Les 2 pièces en haut et en bas sont aussi imprimées pour que l'abat-jour s’emboîte sans avoir besoin de coller. Il vaut mieux garder un accès aux leds ce qui est le cas, il faut soulever le chapeau, la pièce blanche du haut et retirer l'abat-jour.
Le pied de la V1 était petit et donc instable, plutôt que de tout refaire j'ai ajouté un carré de MDF dessous, décallé ca donne un petit air "art déco" pas vilain.
Il faut juste rainurer le dessous pour le passage du câble d'alim et de la prise USB femelle que j'ai collé pour qu'on ne la voit pas mais qu'elle reste accessible pour les mise à jour logiciel.
Pour la peinture c'est du gris anthracite qui est vendu moins de 2€ chez casto en "rouleau échantillon" (en prévoir 2), avec un petit pinceau pour les angles, 2 couches et c'est gagné.
J'aurais préféré une belle laque en bombe mais j'habite en appartement :-/
N'oubliez pas de cacher le support inférieur de l'abat-jour avec du scotch de peintre. Il doit être en place quand on peint faute de quoi vous allez rayer la peinture en le remettant. Celui-là ne pourra plus être enlevé.

Software :
Pour le soft c'est assez rock & roll d'avoir ces bandes en zigzag, je me suis fait quelques migraines nocturnes pour faire défiler du texte ou des symboles sans mettre de matrice en mémoire. Ces bandeaux sont hyper rapides, je pense que je peux envoyer au moins 25 à 30 trames par secondes ce qui est plus que suffisant, il faut ajouter des « delay » dans le code sinon c’est trop rapide.
En ce qui concerne les polices et les symboles je suis resté sur ma macro Excel qui me crache les tableaux de variables binaires ou integer directement en fontions de mes "dessins" monochromes ou couleurs. Il ne plus reste qu'à les coller dans le code.
J'ai découvert la puissance du mot clé PROGMEM qui permet de stocker des tableaux en mémoire flash, une zone bien plus large que la RAM. On peut maintenant envisager le stockage de centaines de "bitmap".
L'ESP se comporte à la fois comme un serveur web (on peut déclencher une séquence en appelant une URL) et comme client (retour d'état, synchro horloge, acquisition météo).
J'ai aussi intégré la bibliothèque "OTA" qui permet de faire des mises à jour du programme en wifi, sans brancher de câble. Il y a aussi une bibliothèque remoteDebug qui permet de debugger à travers une connextion telnet.

En dehors de cela, peu d'évolution depuis la v1, plus de caractères, une police alphanumérique, toujours la synchro ntp pour caler l'horloge, weatherunderground pour récupérer la météo, quelques effets en plus...

On peut bien sur aller chercher des données fournies par jeedom (par exemple), envoyer des données vers jeedom, changer des actionneurs ou déclencher des séquences lumineuses à partir de jeedom. Comme dans la v1.
Avec une google home on peut demander la température du salon et l'afficher sur le lampadaire (via IFTTT et / ou jeedom).

Evolutions :
Je viens de découvrir qu'on peut lire et écrire dans une zone mémoire qui ne se perd pas en cas de coupure d'alimentation.
Ca va me permettre de développer des objets connectés avec un soft "standard" : sans avoir à mettre le SSID wifi et le mot de passe en dur dans le code.
Au premier démarrage on met l’objet en point d’accès wifi, en se connectant dessus et à l’aide d’un navigateur (il faut un serveur dhcp qui retourne toujours la même adresse IP quelques soit l’URL appelée), on affiche un formulaire pour choisir le SSID et entrer le mot de passe du wifi de la maison, on le sauve en mémoire flash. Et c'est fini.
Les fois suivante on peut démarrer directement sur le wifi configuré.
C'est comme cela que fonctionnent la plupart des objets connectés commercialisés aujourd'hui mais j'ignorai jusqu'à peu qu'on pouvait accéder à de la mémoire non volatile.

Peut-être intégrer un capteur de lumière pour ajuster la puissance lumineuse à la lumière ambiante.
Quoi qu'avec weatherunderground on a déjà les heures de lever et coucher du soleil, ça peut aider.

Voilà, il me reste à peaufiner et nettoyer le code (je dis ca mais je sais que c'est le truc qu'on ne fait jamais, on passe à autre chose !).
Je ne le mets pas en téléchargement parce qu'il y a plusieurs librairies et pas mal de code que j'ai pompé à droite ou à gauche et j’ai la flemme de me taper toutes les licences impliquées. Par exemple je ne sais plus ou j'ai trouvé le feu de bois du départ de la vidéo mais chapeau, c'est codé bien propre tout en étant très compliqué, pour le mettre en mode "zigzag" je me suis bien amusé !
Si vous me contactez directement je vous enverrai le source mais vous êtes prévenu, c'est très sale et il y a une quinzaines de fichiers.

Avatar de l’utilisateur
Batto
Messages : 99
Enregistré le : jeu. 17 oct. 2013 20:02
Adhérent Labsud : Adhérent
Localisation : Montpellier
Contact :

Re: Lampadaire Wifi / domotique

Messagepar Batto » lun. 19 mars 2018 17:15

Salut,

Oui heureusement même qu'on peut écrire dans la flash, sinon les bootloader ne pourrait pas exister ;)

Attention pour PROGMEM : la mémoire flash est beaucoup plus lente que la RAM, dans certains cas ça peut poser problème
Président de LABSud

Blog électronique : http://battomicro.wordpress.com/


Retourner vers « Autres »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité