Go Down

Topic: Arduino -> X10 Wireless (Read 4 times) previous topic - next topic

bHogan

After a few bonehead mistakes I have the Arduino interfaced to a CM17A "FireCracker".

The CM17A is a "serial" dongle that sends RF signals to X10 receivers which in turn send signals down the house wiring to control lights and appliances. It's relatively cheap (about 10USD on eBay).

After interfacing through a MAX3232 a nice surprise was that I didn't need it. So its just 3 wires from the Arduino to the RTS, DTR, and GND pins on a DB9 plugged into the CM17A.

For some, this might be a good safe way to control Mains. As I write, my whole house is blinking!

Code: [Select]
/* Arduino Interface to the CM17A Wireless X10 dongle. BroHogan 7/19/08
* The CM17A gets it power and data using only the RTS, CTS, & Gnd lines.
* A MAX232 is not req. (0/+5V work OK) If MAX232 IS used reverse all HIGHs & LOWS
* Signal      RTS DTR        Standby | '1' | Wait | '0' | Wait | '1' | Wait...
* Reset        0   0         _____________________       _____________________
* Logical '1'  1   0   RTS _|                     |_____|
* Logical '0'  0   1         ________       ___________________       ________
* Standby      1   1   DTR _|        |_____|                   |_____|
*
* MINIMUM time for the '1', '0' and 'Wait' states is 0.5ms.
* At least one signal must be high to keep CM17A powered while transmitting.
* Each xmit is 40 bits -> "Header" 16 bits,  "Data" 16 bits, "Footer" 8 bits
* CONNECTION: RTS -> DB9 pin 7.  DTR -> DB9 pin 4. Gnd. -> DB9 pin 7.
*/

#define RTS_pin 2                     // RTS line for C17A - DB9 pin 7
#define DTR_pin 3                     // DTR line for C17A - DB9 pin 4
#define BIT_DELAY 1                    // ms delay between bits (0.5ms min.)
#define ON     0                       // command for ON
#define OFF    1                       // command for OFF
#define BRIGHT 2                       // command for 20% brighten
#define DIM    3                       // command for 20% dim

unsigned int houseCode[16] = {
 0x6000,  // A
 0x7000,  // B
 0x4000,  // C
 0x5000,  // D
 0x8000,  // E
 0x9000,  // F
 0xA000,  // G
 0xB000,  // H
 0xE000,  // I
 0xF000,  // J
 0xC000,  // K
 0xD000,  // L
 0x0000,  // M
 0x1000,  // N
 0x2000,  // O
 0x3000,  // P
};

unsigned int deviceCode[16] = {
 0x0000,  // 1
 0x0010,  // 2
 0x0008,  // 3
 0x0018,  // 4
 0x0040,  // 5
 0x0050,  // 6
 0x0048,  // 7
 0x0058,  // 8
 0x0400,  // 9
 0x0410,  // 10
 0x0408,  // 11
 0x0418,  // 12
 0x0440,  // 13
 0x0450,  // 14
 0x0448,  // 15
 0x0458,  // 16
};

unsigned int cmndCode[] = {
 0x0000,  // ON
 0x0020,  // OFF
 0x0088,  // 20% BRIGHT (0x00A8=5%)
 0x0098,  // 20% DIM    (0x00B8=5%)
};

void setup() {
 pinMode(RTS_pin,OUTPUT);             // onboard LED
 pinMode(DTR_pin,OUTPUT);             // output pin of touch sensor
}

void loop(){   // Sample Commands
 delay(2000);
 xmitCM17A('D',4,OFF);
 xmitCM17A('D',5,ON);
 xmitCM17A('D',5,DIM);
 xmitCM17A('D',5,DIM);
 xmitCM17A('D',5,DIM);
 xmitCM17A('D',5,DIM);
 xmitCM17A('D',5,DIM);
 xmitCM17A('D',5,OFF);
 xmitCM17A('D',4,ON);
}

void xmitCM17A(char house, byte device, byte cmnd){
 unsigned int dataBuff = 0;
 byte messageBuff[5];

 // Build Message by ORing the parts together. No device if Bright or Dim
 if(cmnd == ON | cmnd == OFF){
   dataBuff = (houseCode[house-'A'] | deviceCode[device-1] | cmndCode[cmnd]);
 }
 else dataBuff = houseCode[house-'A'] | cmndCode[cmnd];

 // Build a string for the whole message . . .
 messageBuff[0] = 0xD5;               // Header byte 0 11010101 = 0xD5
 messageBuff[1] = 0xAA;               // Header byte 1 10101010 = 0xAA
 messageBuff[2] = dataBuff >> 8;      // MSB of dataBuff
 messageBuff[3] = dataBuff & 0xFF;    // LSB of dataBuff
 messageBuff[4] = 0xAD;               // Footer byte 10101101 = 0xAD

   // Now send it out to CM17A . . .
 digitalWrite(DTR_pin,LOW);             // reset device - both low is power off
 digitalWrite(RTS_pin,LOW);
 delay(BIT_DELAY);

 digitalWrite(DTR_pin,HIGH);             // standby mode - supply power
 digitalWrite(RTS_pin,HIGH);
 delay(35);                           // need extra time for it to settle

 for (byte i=0;i<5;i++){
   for( byte mask = 0x80; mask; mask >>=1){
     if( mask & messageBuff[i]) digitalWrite(DTR_pin,LOW);  // 1 = RTS HIGH/DTR-LOW
     else digitalWrite(RTS_pin,LOW);                        // 0 = DTR-HIGH/RTS-LOW
     delay(BIT_DELAY);                // delay between bits

     digitalWrite(DTR_pin,HIGH);      // wait state between bits
     digitalWrite(RTS_pin,HIGH);
     delay(BIT_DELAY);
   }  
 }
 delay(1000);                         // wait required before next xmit
}


Enjoy :)
"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

jcgalvezv

Good. As soon as I get my ATmega168 with the Arduino bootloader burned, I am going to work in a project to use TM751 transceiver's daughter board as a universal wireless receiver. I already did it with a PIC12F629.

CM17A and TM751 daughter board with Arduino is the perfect and complete X10 wireless solution.

creatrope

Nice work! Minor typo, you have GND on the DB9 going to pin 4, I believe you mean 5?  Anyway, that works for me!

Note that the Firecracker has both a female and male side. The female side is the one meant to plug in the PC, that's the side I used as the input, and pin 1 is on the upper right, with pin 5 going to the left.   Might not be so obvious if you don't have a PC right in front of you!.

This is a better (and cheaper) solution than the older X10 arduino library using the TW523 unit (actually I had the 1132b).  I wasn't able to get that working reliably.

Thanks,
Harry

bHogan

Harry,
Thanks for pointing out that typo. If I put it on the Playground, I'll correct it there. (Enjoyed your blog, BTW)
I should also include this reference - http://ftp://ftp.x10.com/pub/manuals/cm17a_protocol.txt.

(There are also a lot of "PC" CM17A applications out there, but the only one I found for a micro which was in ASM and used a MAX232.)

jcgalvezv, I'm curious, so you remove the daughter board from the TM751 receiver and use the digital outputs on it?

Thank you both for your feedback.
"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

jcgalvezv

Quote
jcgalvezv, I'm curious, so you remove the daughter board from the TM751 receiver and use the digital outputs on it?
Correct. I also removed the 7805 regulator since I didn't need it.

Go Up