Sunday, January 27, 2013

Controlling Smart Outlet with Arduino

Smart outlets are becoming all the rage. But nobody is opening up an api that can be used by programmers to automate things. I need a smart outlet that I can control with my arduino, so I am going to reverse engineer one of the smart outlets.

I found one on ebay:



Its called "Outdoor Wireless Remote Control AC Power Outlet Plug Switch" and I got mine from ebay seller 'emilyandlily'.

It comes with a remote:


I have connected the outlet to my surge protector and lamp:





When you press the on button on the remote the outlet turns on with a green led.



When you press off the outlet turns off with a red led.


What just happens to be convenient about this outlet for reverse engineering is that the remote runs at 433.92mhz ASK radio frequency. This is convenient because there are tons of cheap off the shelf parts for receiving and transmitting 433.92mhz signals.

We could butcher the remote and then attach it to the arduino frankenstein style but it's not very elegant. 

I'll see what the remote transmits by using an off the shelf 433.92mhz receiver and logic analyzer. Then I will duplicate the signal by writing a code for arduino that sends the same signal through an off the shelf 433.92mhz transmitter.


To see what the remote sends, I have setup a 433.92mhz receiver(Digikey part number AMHRR30-433-ND) on my breadboard.

Pin 1 is connected to 5v
Pin 2 is connected to GND
Pin 3 is left alone
Pin 4 is GND
Pin 5 is GND
Pin 7 is 5v
Pin 8 you can connect to an oscilloscope to see the signal if you want to. I haven't connected it to anything.
Pin 9 is where the signal that the receiver sees is outputted. This is where I will connect my logic analyzer.
Pin 10 is connected to 5v



For my logic analyzer I am using a "Saelae Logic", it has OSX compatibility, so I can connect it to my mac mini. I got the logic analyzer because I already have an oscilloscope, but if I were to start over again(no scope + no logic analyzer), I would get the "QA100 USB Oscilloscope." You can google them to see.

So below I have attached my logic analyzer yellow lead to the receiver's data out pin 9. I have attached the ground lead to GND. Also I have placed the rest of the wires away from the sensing wires because they can cause erroneous readings if they are too close.



So with the logic analyzer software running and the circuit powered, I press "ON" on the remote. Here is what comes up:



Here is what comes up when I press OFF:



So all I need to do is make my Arduino send the same signals to turn the outlet on and off. I will use another off the shelf transmitter to do this.

Where do you get the 433.92mhz transmitter? Well I got mine from ebay. Search "arduino 433mhz transmitter." They come in a pair, one receiver one transmitter.  Below are the ones I bought.


Here is a pic of the arduino connected to the transmitter. The transmitter has 5v, GND, then it's data pin is connected to arduino digital pin 2.




I need to note two things, first you need to use a 6.8inch antenna, it is the orange wire above. This makes the transmission so much more effective and reliable. The second is that the power to the transmitter needs to be clean, USB power is too noisy. You can see I am using a 9v ac/dc adapter for the arduino.

I already know what I want from looking at what the logic analyzer showed me, so I just programmed:


int transmitPin = 2; 

void setup()
{
  pinMode(transmitPin,OUTPUT);
  digitalWrite(transmitPin,LOW);
}

void loop()
{
     turnOn();
     turnOn();
     turnOn();
     turnOn();
     delay(1000);
     turnOff();
     turnOff();
     turnOff();
     turnOff();
     delay(1000);

  
}


void customDelay(unsigned long time) 
{
    unsigned long end_time = micros() + time;
    while(micros() < end_time);
}

//1000=1ms
void setStateWithDelay(int pin, int state,int delayTime)
{
  if(state==1)
    digitalWrite(pin,HIGH);
  else
    digitalWrite(pin,LOW);
    
  customDelay(delayTime);
}

void turnOn()
{
    
  setStateWithDelay(transmitPin,0,13000);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
   
   digitalWrite(transmitPin,LOW);
}

void turnOff()
{
  setStateWithDelay(transmitPin,0,13000);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,1270);
  setStateWithDelay(transmitPin,0,430);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
   setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
 
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
 
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
 
  setStateWithDelay(transmitPin,1,430);
  setStateWithDelay(transmitPin,0,1270);
 
  setStateWithDelay(transmitPin,1,430);
 
    digitalWrite(transmitPin,LOW);
 
  
}




This turns my lamp on and off. You may have noticed that I send turnOn() 4 times, it seems that the outlet wants 4 signals to turn on before it does. Same for the off signal.

Here is a video of the whole circuit working

I don't know if all of the outlets sold have a unique remote id or if they all have one command. I axed the ebay item seller if they know the answer to this question but haven't gotten a reply yet.

Here are the exported output signals

Here are the signals that you can open in the Saelae logic analyzer program.







Saturday, December 29, 2012

Starcraft 2 Cybercore Badge Journal

Update January 17th 2013: Now that I am done playing with the badge it is up for sale.

So I got the idea to make a electronic badge... my idea was to make a chronoboosted cybercore.

I picked a attiny45 and decided to do charlieplexing for the leds. Here is where I found out that ATTiny is supported by a 3rd party for the Arduino IDE

The part that I picked was SMD, so for prototyping I got a DIP adapter ready with solder paste...

Time to heat up the hot air station to melt the solder paste.

Here we go

All done!


Now to prototype a circuit. I have added power and another breakout board for the programmer, as well as an led to test the blink program.


It works!


Now I need to design a pcb. The first thing is, I need to add the battery holder to my CAD program. It looks like this.



Here I have finished adding it to the CAD program. I use Eagle btw.


Time to lay out the pcb.

Now to route the traces.

Finish generating the files.

Heres a better look at the wire routing. Need to make sure that the wires don't cross inappropriately.


Ordered a set from batchpcb. Here they came in!

I have ordered parts already to populate the pcb.


So here is the pcb with solder paste applied to the led pads.

To put things in perspective, the leds are 0603 size. Not as easy to solder.


Here is the pcb with the leds placed on the solder paste.

Time to heat up the hot air station again.
All done!
Now I solder the components on the other side with a soldering iron. (If I use hot air on the opposite side then the led solder will melt and they will fall off). I used flux to solder the ATTiny.

This is how it looks with everything soldered from the top.
Funny story, when I originally ordered parts I also ordered a CR2032 battery, but mouser wanted me to pay 7$ to ship a 0.45 cent battery. They don't ship them in cheaper shipping like priority mail because they can explode and catch the package on fire, that is what the support lady told me. So I took the battery off my order. Then I went to pick up a battery the day I assembled the board, but because it was Christmas Eve, all the shops were closed. I decided to solder two power wires so I could use an external power supply.

All ready to program.
It works!

 A video is here. One thing to note is that in real life it looks more like a chronoboosted cybercore because the leds leave an after image in your eye. There also isn't any lense flare. So tomorrow I will buy a battery then cut off the power wires and glue a safety pin to it so I can wear it.


So I found some coincells in my dresser! Here is another video.

Thursday, September 13, 2012

YAMAKASI Catleap Q270 LED SE 27 Monitor is Mac Compatible

For coding, this is the same step up for me that going from a 1280x1024 to 1920x1080 made, in terms of making it easier to work. The Catleap Q270 SE is compatible with my 2009 mac mini.


You have to make sure that you have a display port to dual link dvi adapter. Whatever you have, make sure you can find a dual link dvi adapter. I am using the 99$ Apple display port to dual link dvi adapter. One thing to note is if you use this adapter, make sure to plug the usb portion of it in, otherwise it will not work.






The monitor comes with it's own power brick.


One thing to note is that if you turn the monitor off for some time, and then turn it back on, there is some fuzziness, which can be solved by unplugging the dual link dvi cable and replugging it back in. I don't know why this happens.


Here is a close up of the same area of the screen, fuzziness with and without.



Xcode is going to be way more easier to use with this screen. For $329 off ebay I do consider it a deal. When I hook it up to my pc for gaming, it goes to 120hz. I didn't even buy the 2B specific version.

Monday, September 3, 2012

Arduino Dormant Labs PH Shield Tutorial

UPDATE: This product has been replaced by its successor:
          http://rezaalihussain.blogspot.com/2014/04/measuring-ph-using-dormant-labs-ph.html

Here is a quick setup guide to help you get started measuring ph using arduino.

You will need:


1. Take your arduino and insert the ph shield on top of it.
2. Connect your PH Probe to the shield.

3. Download the Arduino Dormant Labs PH Shield Sketch , open it in the arduino IDE, and then upload. If you do not have the Arduino IDE installed, go to the Arduino site. Make sure you are using arduino IDE 1.0 or higher.

4. After uploading, open the serial monitor. The button is in the top right hand side of the Arduino IDE. It should start showing scrolling text similar to below. Don't worry about the values yet, they will be correct once we calibrate the ph probe. Leave this serial monitor window open on your computer.


5. Pour the 7.0 calibration solution into one cup, the 4.0 calibration solution into a second cup, and tap water into the third.
6. Start by rinsing your ph probe in the tap water.
7. Now immerse the tip of the probe into your 7.0 calibration solution. Swirl it around for 10 seconds, then press the calibrate button on the ph shield.

8. Now re-rinse the probe in the water.
9. Now immerse the probe in the 4.0 calibration fluid, swirl around for 10 seconds, and then press the calibrate button.
10. Your ph shield is now calibrated! The serial monitor in the arduino ide now will show correct information. You can now alter the sketch however you like.