J’ai récemment acheté un système d’éclairage LED avec télécommande Radio Fréquence. Celle-ci est composée de quatre boutons (On/Off, Synchronisation, Couleur, Variation). Nous allons voir comment connecter facilement cette télécommande à notre réseau et ainsi la piloter par n’importe quelle interface (iPhone dans mon cas).
Pour cela, nous allons utiliser un Arduino avec Shield Ethernet (j’ai choisi l’ENC28J60 car moins cher que l’officiel) et un composant électronique l’ULN2803 (merci Michaël pour la découverte).
Le principe et de programmer l’Arduino pour qu’il écoute les requêtes HTTP. S’il reçoit un GET qu’il comprend, alors il change l’état d’une de ses sorties. L’ULN2803, permet de simuler l’appui sur une touche de la télécommande en reliant la partie soudée à la masse (c.f. schéma).
Ainsi, avec un simple GET (exemple : http://192.168.1.11/bouton/onoff) vers l’Arduino, je suis capable d’allumer l’éclairage LED. En associant plusieurs combinaisons de touches et actions successives, je peux également choisir la couleur ou le mode de variation.
Schéma de l’ULN2803
Schéma de câblage
Les tests de câblage
Le résultat
Code source Arduino
#define DEBUG 1 //#undef DEBUG #include "EtherCard.h" #define pinO 2 #define pinC 3 #define pinP 4 boolean actionOnoff = false; boolean actionBlanc = false; boolean actionBleu = false; boolean actionVert = false; boolean actionJaune = false; boolean actionRouge = false; boolean actionViolet = false; boolean actionVariation1 = false; boolean actionVariation2 = false; boolean actionVariation3 = false; boolean actionVariation4 = false; // please modify the following three lines. mac and ip have to be unique // in your local area network. You can not have the same numbers in // two devices: static uint8_t mymac[6] = { 0x00,0x24,0x41,0x55,0xF6,0x53 }; //Static IP //static byte myip[] = { 192,168,1,114 }; //static byte gwip[] = { 192,168,1,1 }; // #define MYWWWPORT 80 #define BUFFER_SIZE 700 byte Ethernet::buffer[BUFFER_SIZE]; BufferFiller bfill; #define STR_BUFFER_SIZE 22 static char strbuf[STR_BUFFER_SIZE+1]; uint16_t http200ok(void) { bfill = ether.tcpOffset(); bfill.emit_p(PSTR( "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n")); return bfill.position(); } // prepare the webpage by writing the data to the tcp send buffer uint16_t print_webpage() { bfill = ether.tcpOffset(); bfill.emit_p(PSTR( "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" "<html><body>Invalid option selected</body></html>")); return bfill.position(); } #define CMDBUF 50 int16_t process_request(char *str) { int8_t r=-1; int8_t i = 0; char clientline[CMDBUF]; int index = 0; int plen = 0; #ifdef DEBUG Serial.println( str ); #endif char ch = str[index]; while( ch != ' ' && index < CMDBUF) { clientline[index] = ch; index++; ch = str[index]; } clientline[index] = '\0'; #ifdef DEBUG Serial.println( clientline ); #endif // convert clientline into a proper // string for further processing String urlString = String(clientline); if(urlString == "/bouton/onoff"){ Serial.println("Action ON/OFF"); actionOnoff=true; } if(urlString == "/couleur/blanc"){ Serial.println("Action BLANC"); actionBlanc=true; } if(urlString == "/couleur/bleu"){ Serial.println("Action BLEU"); actionBleu=true; } if(urlString == "/couleur/vert"){ Serial.println("Action VERT"); actionVert=true; } if(urlString == "/couleur/jaune"){ Serial.println("Action Jaune"); actionJaune=true; } if(urlString == "/couleur/rouge"){ Serial.println("Action ROUGE"); actionRouge=true; } if(urlString == "/couleur/violet"){ Serial.println("Action VIOLET"); actionViolet=true; } if(urlString == "/mode/variation1"){ Serial.println("Action VARIATION1"); actionVariation1=true; } if(urlString == "/mode/variation2"){ Serial.println("Action VARIATION2"); actionVariation2=true; } if(urlString == "/mode/variation3"){ Serial.println("Action VARIATION3"); actionVariation3=true; } if(urlString == "/mode/variation4"){ Serial.println("Action VARIATION4"); actionVariation4=true; } return( http200ok() ); } void setup(){ pinMode(pinO, OUTPUT); pinMode(pinC, OUTPUT); pinMode(pinP, OUTPUT); Serial.begin(9600); Serial.println("ENC28J60/Nanode/EtherCard RESTduino"); if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0) { //#ifdef DEBUG Serial.println( "Failed to access Ethernet controller"); //#endif while(1); } // Setup static IP address //ether.staticSetup(myip, gwip); if (!ether.dhcpSetup()) Serial.println("DHCP failed"); ether.printIp("My IP: ", ether.myip); ether.printIp("Netmask: ", ether.mymask); ether.printIp("GW IP: ", ether.gwip); ether.printIp("DNS IP: ", ether.dnsip); #ifdef DEBUG Serial.println("Ready"); #endif } void loop(){ uint16_t plen, dat_p; int8_t cmd; while(1) { // read packet, handle ping and wait for a tcp packet: dat_p=ether.packetLoop(ether.packetReceive()); /* dat_p will be unequal to zero if there is a valid http get */ if(dat_p==0){ // no http request continue; } // tcp port 80 begin if (strncmp("GET ",(char *)&(Ethernet::buffer[dat_p]),4)!=0){ // head, post and other methods: dat_p = print_webpage(); goto SENDTCP; } // just one web page in the "root directory" of the web server if (strncmp("/ ",(char *)&(Ethernet::buffer[dat_p+4]),2)==0){ #ifdef DEBUG Serial.println("GET / request"); #endif dat_p = print_webpage(); goto SENDTCP; } dat_p = process_request((char *)&(Ethernet::buffer[dat_p+4])); SENDTCP: if( dat_p ) ether.httpServerReply( dat_p); //Partie Action if(actionOnoff==true){ digitalWrite(pinO, HIGH); delay(300); digitalWrite(pinO, LOW); actionOnoff=false; } if(actionBlanc==true){ digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); delay(100); digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); actionBlanc=false; } if(actionBleu==true){ digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); for(int i=1;i<=2;i++){ delay(100); digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); } actionBleu=false; } if(actionVert==true){ digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); for(int i=1;i<=6;i++){ delay(100); digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); } actionVert=false; } if(actionJaune==true){ digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); for(int i=1;i<=8;i++){ delay(100); digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); } actionJaune=false; } if(actionRouge==true){ digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); for(int i=1;i<=10;i++){ delay(100); digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); } actionRouge=false; } if(actionViolet==true){ digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); for(int i=1;i<=11;i++){ delay(100); digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); } actionViolet=false; } if(actionVariation1==true){ digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); delay(100); digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); actionVariation1=false; } if(actionVariation2==true){ digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); for(int i=1;i<=2;i++){ delay(100); digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); } actionVariation2=false; } if(actionVariation3==true){ digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); for(int i=1;i<=3;i++){ delay(100); digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); } actionVariation3=false; } if(actionVariation4==true){ digitalWrite(pinC, HIGH); delay(300); digitalWrite(pinC, LOW); for(int i=1;i<=4;i++){ delay(100); digitalWrite(pinP, HIGH); delay(300); digitalWrite(pinP, LOW); } actionVariation4=false; } } } |
Résultat final (avant et après)
Bien sûr, ce principe s’applique à tout système composé de boutons. On peut alors facilement contrôler sa porte de garage, son alarme, ou tout autre objet.
Ça en devient presque trop facile ;-)
Arnaudr
mai 13th, 2012 à 23:21