This was the time to give a brain to the thingy, in other words how to control the thing. My first approach was to create a web browser, running in the arduino based on the example of the enc28j60 library. I wanted to press a button on a webpage, set the relay, delay for a few seconds and return to the original condition. I produced the following code:
// This is a demo of the RBBB running as webserver with the Ether Card // 2010-05-28 http://opensource.org/licenses/mit-license.php #include <EtherCard.h> #define RELAY 10 #define LED 2 // ethernet interface mac address, must be unique on the LAN static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; static byte myip[] = { 192,168,1,203 }; byte Ethernet::buffer[1000]; BufferFiller bfill; char * color = "green"; char * state = "fechada"; int changed_state= 0; void setup () { Serial.begin(9600); if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) Serial.println(F("Failed to access Ethernet controller")); ether.staticSetup(myip); } const char http_OK[] PROGMEM = "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n\r\n"; const char http_Found[] PROGMEM = "HTTP/1.0 302 Found\r\n" "Location: /\r\n\r\n"; const char http_Unauthorized[] PROGMEM = "HTTP/1.0 401 Unauthorized\r\n" "Content-Type: text/html\r\n\r\n" "<h1>401 Unauthorized</h1>"; static word homePage() { bfill = ether.tcpOffset(); if(changed_state == 0){ bfill.emit_p(PSTR( "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" "<meta http-equiv='refresh' content='1' />" "<title>OPEN ZEZZAWEE</title>" "<body bgcolor='green'>" "<h1>Porta esta fechada</h1>" "<INPUT Type='BUTTON' VALUE='porta' ONCLICK='window.location.href=\"/?cmd=porta\"'>")); return bfill.position(); } else{ bfill.emit_p(PSTR( "HTTP/1.0 200 OK\r\n" "Content-Type: text/html\r\n" "Pragma: no-cache\r\n" "\r\n" //"<meta http-equiv='refresh' content='1' />" "<title>OPEN ZEZZAWEE</title>" "<body bgcolor='red'>" "<h1>Porta esta aberta</h1>" "<INPUT Type='BUTTON' VALUE='porta' ONCLICK='window.location.href=\"/?cmd=porta\"'>")); return bfill.position(); } } void loop () { word len = ether.packetReceive(); word pos = ether.packetLoop(len); if (pos) { bfill = ether.tcpOffset(); char *data = (char *) Ethernet::buffer + pos; if (strncmp("GET /", data, 5) !=0){ bfill.emit_p(http_Unauthorized); } else { data +=5; if (data[0] == ' '){ homePage(); } else if ((strncmp("?cmd=porta", data,10) ==0) && changed_state ==0){ Serial.println("Im here"); digitalWrite(RELAY,HIGH); Serial.println("Open..."); delay(5000); changed_state=1; bfill.emit_p(http_Found); } else if ((strncmp("?cmd=porta", data,10) ==0) && changed_state ==1){ digitalWrite(RELAY,LOW); Serial.println("Closed..."); changed_state=0; bfill.emit_p(http_Found); } } ether.httpServerReply(bfill.position()); // send web page dat } }
The trouble with this code is that it behaved like a flip-flop, it just changed the state based on the current state, so if the door was locked, it was unlocked and stayed that way until a new button press.
After some thinking I realized I didn't need to use TCP on this application, i just needed some way to receive a UDP package, check its validity and if valid open the door for the specified amount of time. Again based on a example of the ehternet library this was what i got:
//Open Zezzvw3 - Door unlocking mechanism // 2014-11-29 glitchmaker <glitchmakers at gmail dot com> // based on the UDP example from // 2013-4-7 Brian Lee <cybexsoft at hotmail dot com> #include <EtherCard.h> #include <IPAddress.h> #define STATIC 1 // set to 1 to disable DHCP (adjust myip/gwip values below) #define RELAY 10 #define LED 2 #if STATIC // ethernet interface ip address static byte myip[] = { 10,1,21,250 }; // gateway ip address static byte gwip[] = { 10,1,21,254 }; #endif // ethernet mac address - must be unique on your network static byte mymac[] = { 0x70,0x69,0x69,0x2D,0x30,0x31 }; void blink_OK(void){ digitalWrite(LED,HIGH); delay(300); digitalWrite(LED,LOW); delay(300); } void open_door(void){ Serial.print("Opening door for 5 seconds"); digitalWrite(RELAY,HIGH); digitalWrite(LED,HIGH); delay(5000); digitalWrite(RELAY,LOW); digitalWrite(LED,LOW); Serial.print("It's Closed Again!"); } byte Ethernet::buffer[500]; // tcp/ip send and receive buffer //callback that prints received packets to the serial port void udpSerialPrint(word port, byte ip[4], const char *data, word len) { Serial.println(data); if (strncmp("OPEND0123",data,9)==0){ open_door(); } else{ blink_OK(); Serial.println("Do I know YOU?"); } } void setup(){ Serial.begin(57600); Serial.println(F("\n[backSoon]")); int count=0; if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) Serial.println(F("Failed to access Ethernet controller")); #if STATIC ether.staticSetup(myip, gwip); #else if (!ether.dhcpSetup()) Serial.println(F("DHCP failed")); #endif ether.printIp("IP: ", ether.myip); ether.printIp("GW: ", ether.gwip); ether.printIp("DNS: ", ether.dnsip); //register udpSerialPrint() to port 1337 ether.udpServerListenOnPort(&udpSerialPrint, 1337); //register udpSerialPrint() to port 42. ether.udpServerListenOnPort(&udpSerialPrint, 42); pinMode(LED,OUTPUT); digitalWrite(LED,LOW); pinMode(RELAY,OUTPUT); digitalWrite(RELAY,LOW); for(count=0;count <=3;count++){ blink_OK(); } } void loop(){ //this must be called for ethercard functions to work. ether.packetLoop(ether.packetReceive()); }At first it all seem to run, but then I notice that after a few uses the thingy became unresponsive and I needed to reset it. The solution was simple: add a watchdog timer and let it auto reset every time it became unresponsive. All I needed was to add the following lines:
#include <avr/wdt.h> void setup(){ . . . . wdt_enable(WDTO_1S);//This start the watchdog timer with a 1 second timeout. } void loop(){ wdt_reset();//This resets the timer . }
I know what I've done. Since the delay is of five seconds, the watchdog timer timeouts every time the door is unlocked. This way I am sure that the device is always ready.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.