Sunday, December 8, 2013

Realtek RTL8192CU WiFi adapter problems on BeagleBone Black

I recently bought a BeagleBone Black (BBB) to act as my home automation server. This is a really nice board, the size of a credit card, but with quite powerful processor ARM A8 at 1 GHz - equivalent to the initial iPhone. It has a big expansion connector for adding different control boards, called "capes".
It can run Linux or Android OS. And, it costs only $45 (http://www.makershed.com/BeagleBoard_BeagleBone_Black_p/mkcce3.htm)



The only problem is that it does not have a WiFi card built-in. But, you can plug a USB-based WiFi dongle. Edimax EW-7811n is very cheap (<$10 on Amazon: http://www.amazon.com/Edimax-EW-7811Un-Wireless-Adapter-Wizard/dp/B003MTTJOY/ref=sr_1_2?ie=UTF8&qid=1386476449&sr=8-2&keywords=edimax) and supposedly works well on BBB Ubuntu Linux out-the-box. Or, that's what I thought...

After following instructions on the web to configure the the WLAN settings to connect to my secure router, I got it to work, kind of. It was very unstable, very slow and working only once in a while. I could not ping any external servers with it only explicit IP addresses on my network (if it was in the mood). I searched and searched web for updated drivers and solutions. Some drivers I downloaded did not work at all, and hosed even my wired Ethernet LAN. Some posts warned about using underpowered power supply or advocated to use a USB extension cable to reduce electronic interference. Nothing helped. Finally, I stumbled onto this blog post by +Darshan Gencarelle:

http://gencarelle.com/blog/2013/07/19/problems-with-rtl8188cus/

He modified the driver Makefile and described the process of driver compilation and installation. I just changed the portions referring to header files for my Ubuntu distribution version and this worked beautifully. WiFi seems now to be solid and work every time I try. I will test it for the next few days, but my hopes are high the problem is solved now.

I still have one more issue to solve with my BBB Ubuntu setup. The clock seems to come up with wrong date & time whenever I reboot. This is not good, since I intend to use this system to automatically run my sprinkler schedule and we have municipal watering date & time restrictions.. I wouldn't want to get a fine just because my sprinkler controller decided to boot up with wrong time setting...

PS. I also tested this with this generic WiFi adapter (which also uses RTL8192CU chip from RealTek), I bought from Makershed.com:
http://www.makershed.com/WiFi_802_11b_g_n_Module_For_Raspberry_Pi_More_p/mkad55.htm
It seems to work the same as the Edimax adapter.

PS2: I tried to run the board just from USB supplied by my PC and it does not work well. The power supplied by my PC USB host is not enough to run the whole system with WiFi. So, the advice about using sufficient power supply is a valid one.


Saturday, December 7, 2013

Turning dumb wireless wall plugs into the smart ones (Part 1)

I just bought Stanley wireless wall plug system from Amazon. It has three wall plugs which can be remotely turned off or on by a small transmitter. I want to control these wall plugs via internet from anywhere in the world. There are such products on the market, such as Belkin WeMo, but they are much more expensive (~$50 per one plug). This set cost me $21 for three plugs (http://www.amazon.com/gp/product/B00A3XTCOE/ref=ox_ya_os_product).

The nice aspects of this product are:
1. The remote has separate on and off buttons which will be useful if controlling plugs remotely, without seeing the effect.
2. The plug has on/off button in case I want to override the setting without a remote or access to internet
3. The system works with fixed digital codes transmitted via RF at standard 433MHz. Generic 433MHz transmitters and receiver modules that connect to microcontrollers such as Arduino can be readily bought.
4. The system has a good range, covering pretty much my whole house (signal can go through multiple walls)


So, the plan is as follows:
1. Create a sniffing circuit to determine what codes are transmitted by each button on the transmitter. For this I will use a simple 433 MHz receiver I bought from Amazon for $6 (including a matching transceiver)
2. Program a microcontroller (in my case TI's MSP430, similar to Arduino) to programmably play back the codes via the above mentioned simple 433MHz transmitter. (Later, I will connect this TX to a small webserver I'm building, based on BeagleBone Black, instead of MSP430).
3. Test the whole thing
4. Port this to BeagleBone Black webserver which will act as the home automation hub.

1. The sniffing circuit

I found this idea from several sources on the web, but this is ingenious. I used this tiny RX module I bought from Amazon (http://www.amazon.com/gp/product/B008A4UWK6/ref=oh_details_o03_s01_i00?ie=UTF8&psc=1)
(TX is on the left and RX is on the right)

Then, I made a simple circuit with a resistor divider and customized cables (USB power and audio jack) that I will attach to my computer which will be used as an oscilloscope.

Here is what it looks like:



I plugged both cables (USB and audio) into USB and Line-in sockets in the PC, respectively. It's important to use Line-in, not microphone, socket as it can handle larger voltage swings, without damaging a sound card.
Next, I downloaded an open source software - Audacity (http://audacity.sourceforge.net/download/) which I used to capture the input from the Line-in input on the sound card while I pressed each button on the remote control. I used sampling at 44.1 kHz which is fast enough to capture decoded signal from the RX module:



As you can see the code repeats as long as you press the button. I labeled different waveform, so I can later read the code for each button. The codes have some minor differences among them for a few bits:


Now, I needed to find out the timing of the pulses, so I zoomed in till I saw individual sample points and measured how many of them are in high and low pulses as well as in the period:




2. A microcontroller program 

I will use this information above to program the MSP430 microcontroller LaunchPad with TX module to play back the codes at will (the LaunchPad can be replaced by anything else, such as Arduino Uno). I connected VDD of the TX module to 5V (instead of 3.3V) to get a better range. The TX Data pin is connected to P1.1 of the LaunchPad. The Launchpad is programmed and power is supplied via USB cable connected to my PC.



Here is the Energia software code for the LaunchPad: http://tinkeringandsuch.blogspot.com/2013/12/example-energia-code-for-controlling.html


3. Testing

I finally got the whole setup to work. You can see the power-on indicator lamp flashing on the power plug:



4. Porting to BeagleBone Black webserver 

Now, to make this thing more useful, I will port the software into my BeagleBone Black board which runs a webserver under Ubuntu Linux. This way a can control devices attached to these wall plugs over the internet and include them into my home automation project I am building. I will describe this step in a second part of the blog entry.

Example Energia code for controlling 433MHz RF transmitter with a microcontroller

// Example Energia code for controlling 433MHz RF transmitter
// I tested this code on MSP430G2553 microcontroller on MSP-EXP430G2 LaunchPad board
// This code should be able to run on Arduino with minor modifications

// Creative Commons Attribution-ShareAlike 3.0 license
// by Roman Staszewski
// December 2013

#define TX_DATA_PIN   2

#define SHORT_PULSE (345)  // time in us. This may need to be fine tuned for a different RF system
#define LONG_PULSE  (1070) // time in us. This may need to be fine tuned for a different RF system
#define BLANK_DELAY (9400) // time in us. This may need to be fine tuned for a different RF system

#define NUM_CHAR 27  // number of characters in the code for the devices I want to control

const int TxPin =  TX_DATA_PIN;      // The number of the TX data pin on my MCU device that is connected to my RF TX module. This assignment may be different on another MCU

char test_code_ch_on[NUM_CHAR+1] = "011101111111100111111010111";  //Channel ON code
char test_code_ch_off[NUM_CHAR+1] = "101101111111100111111010111";  //Channel OFF code

unsigned long time;
unsigned long time2;

void setup() {
  // Initialize TXPin
  pinMode(TxPin, OUTPUT);
  digitalWrite(TxPin, LOW);
}

void loop()
{
  // toggle switch every three seconds
  time = millis();  // get current time in milliseconds
  do {
  send_code(test_code_ch_on);  // transmit code
  time2 = millis();  // get current time in milliseconds
  } while ((time2 - time) < 3000);

  time = millis(); // get current time in milliseconds
  do {
  send_code(test_code_ch_off);  // transmit code
  time2 = millis();  // get current time in milliseconds
  } while ((time2 - time) < 3000);
}

// This function sends either encoded 0 or 1 pulse to the digital output pin connected to data pin of the TX module
// my TX module has polarity inversion, so I'm writing HIGH to TxPin instead of LOW below (and vice versa)
void transmit_bit(int single_bit)
{
  if(single_bit == LOW) {   // send encoded '0'
    digitalWrite(TxPin, HIGH);  
    delayMicroseconds(LONG_PULSE);                
    digitalWrite(TxPin, LOW);
    delayMicroseconds(SHORT_PULSE);  
  }
  else {                 // send encoded '1'
    digitalWrite(TxPin, HIGH);
    delayMicroseconds(SHORT_PULSE);                
    digitalWrite(TxPin, LOW);
    delayMicroseconds(LONG_PULSE);
  }
}

// This function provides a time gap between sending codes
void transmit_blank()
{
  digitalWrite(TxPin, LOW);
  delayMicroseconds (BLANK_DELAY);
}

// This function sends an arbitrary code the the TX
void send_code(char* code)
{
  for (int i=0; i< NUM_CHAR; i++) {
    if(code[i] == '1')
      transmit_bit(HIGH);
    else if(code[i] == '0')
      transmit_bit(LOW);
  }

  transmit_blank(); // transmit time gap at the end
}