-
Placing the thingy
01/02/2015 at 20:15 • 0 commentsIt was then the time to place the thingy. Since the box would be placed under the floor with no power supply around, I choose to use a PoE adapter. It looks like this already on place near the main switch:
And on the final resting place of the thingy we have this (the nail it's not part of this project):
And so it ends. Now almost everyone on my office wants the software on their PC.
-
Bossing the thingy around
01/02/2015 at 10:15 • 0 commentsAs I have chosen the UDP path to control the thingy, I needed a way to send the command datagrams to it. The UDP receive example I used for the arduino, included a processing example for UDP send. After messing around a little bit with processing, I got this:
import hypermedia.net.*; UDP udp; // define the UDP object boolean overDoorButton = false; PFont f; void setup() { udp = new UDP( this, 31337 ); // create a new datagram connection on port 31337 udp.listen( true ); // and wait for incoming message size(220,190); f=createFont("Arial",16,true); } void draw() { background(10,250,50); textFont(f,16); fill(0); if (overDoorButton == true) { fill(200,100); }else { noFill(); } rect(35, 60, 150, 75); text("ABRIR",85,100); } void mousePressed() { String ip = "xx.xx.xx.250"; // the remote IP address int port = 1337; // the destination port if(overDoorButton){ udp.send("OPEND0123", ip, port ); // the message to send } } void mouseMoved() { checkButtons(); } void mouseDragged() { checkButtons(); } void checkButtons() { if (mouseX > 35 && mouseX < 185 && mouseY > 60 && mouseY < 135) { overDoorButton = true; } else { overDoorButton =false; } } void receive( byte[] data ) { // <-- default handler //void receive( byte[] data, String ip, int port ) { // <-- extended handler for(int i=0; i < data.length; i++) print(char(data[i])); println(); }
The graphic result is something like this:To unlock the door, just press the button, and presto! One less excuse to get up and walk.
-
The brain of the thingy
01/01/2015 at 14:54 • 0 commentsThis 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.
-
Making the thingy
01/01/2015 at 11:18 • 0 commentsSo the time to make the board has come. I pick my etching solution, an old Bakelite PCB board, clothing iron and laser printed circuit. I transferred the image to the copper, placed the board on the etch solution and waited.... and waited... and waited... At the end of the day a had nothing etched, with lots of copper on the board. I then decided to keep the board over night in the solution. Really bad idea! Next day I had almost nothing on the board, no copper but also no toner on most of the circuit. All I had left was a sad looking board pleading me to end it's misery. And so I did it.
As I didn't want to fine tune the etch solution (too strong?, to weak? at this point i don't even know...) I chose to use a perfboard for the main board, following the schematic for the board.
The rest of the assembly was uneventful, just solder the wires and the components to the board. In the end I had this:
-
The hardware thingy
01/01/2015 at 11:04 • 0 commentsForm the first moment I envisioned this I always wanted to use an Ethernet connection in order to communicate with the device. I followed the (very) easy path of using the enc28j60 with the arduino. As I didn't want to use a full arduino board on this project, I also wanted to design a custom board to house the micro-controller.
With these premises i projected a board with power supply, the micro, a LED and a relay. The Ethernet connection would be provided by a separate ready made board. All of this would be enclosed on a plastic box and placed under the floor.
For the board I ended up with this scheme:
And this resulted on this board:
All of this seems that it was all easy peasy.... but no...
-
Laziness is the stepmother of invention
12/31/2014 at 21:06 • 0 commentsWhere I work we have a safety door with an unlocking mechanism.
A long time before I started work there, the door was locked and anyone that wanted to enter ringed a bell, and someone inside would press a button under the desk in order to unlock the door. This was all working fine until it was needed to do some renovations on the floor of the room. The cables to all the buttons under the desks were cut and the door stayed open during work hours ever since. The trouble was that some times we have team meetings in this room and the door needs to be closed. So if any one rings, one of us, has to go and open the door. Joining some laziness with the excuse to build something, this project has born.