Handheld X-10 Wireless Transmitter
Credits: Stewart Baker baker@nildram.co.uk
|
Disclaimer: The author regrets he is unable to supply any hardware etc. The software in this article is for personal use only, and not for any commercial gain. No liability is accepted for any damage or inconvenience, however caused. BackgroundFor some time I have been interested in Home Automation, and all its trials and tribulations. Living in the UK, Home Automation has proved to be a rather expensive hobby as most X10 equipment is priced 2 or 3 times that of the same item from the US. However, I have been fortunate to purchase a number of units on business trips to the States, and have successfully modified most of them to work in England. My present system is a dedicated 486 running Homeseer software. The hardware consists of a CM11A computer to X10 interface and a number of appliance and lamp modules. I also have a homebrew IR system that links the computer to my VCR, HIFI and TV. The "human" input to the system is via a Marmitek hand held controller which in addition to having IR learning capability can also send X10 commands via an RF signal at 418MHz. These signals are picked up by a TM12U RF to X10 unit (the Euro version of the RR501) and sent via the mains wiring to the Homeseer program from the CM11A. Wishing to further expand my system, I decided to see if I could build a RF Transmitter unit that would communicate with the TM12U and allow me more inputs into my X10 system. My first stop was an article by Edward Cheung Ph.D. on "Data format for X-10 wireless units". This gave me an idea of what the protocol for the RF data transmission should be. However I decided to check it out with my set up as the article was based on an RT-504 not a TM12U. Using a scope to look at the output from a 418MHz receiver I observed that the format was basically as described, however it had one subtle difference. Instead of 32 "1" samples per frame it had 33. I don't know why! Being familiar with PIC microcontrollers, and having already used them for a number of remote control applications they have proven to be an excellent choice yet again. Circuit DescriptionThe circuit diagram of the Handheld X-10 Wireless Transmitter
is shown in the figure below
Central to the unit is a PIC Microchip type 16C84. This is an 8 bit microprocessor with
separate internal busses for memory and data. It has an internal divide by 4 connected
between the oscillator and the internal clock bus. This makes instruction times easy to
calculate if one uses a 4MHz crystal. Each instruction cycle is then 1uS.
13 I/O pins are available each with individual directional control. These are defined as PORTA (RA0-RA3) and PORTB (RB0-RB7). In this circuit only one PORTA pin is used (RA0). The output data stream comes from this pin and via a 330 ohm resistor drives TXM. The 270pF capacitor is for RF decoupling. TXM is an AM RF Transmitter Module comprising a two terminal high stability oscillator designed for short range data/remote control applications at 418 or 433MHz. These modules are ideal for the RF - X10 applications as they need the minimum of extra components to function. In the UK the modules are available from Maplins Part # NV08J. For US units, a part that operates at 310MHz is needed. The antenna is a short length of wire fitted inside the plastic box that holds the unit. PORTB is used to read the keypad. This is also from Maplins (Part # JM09K) this is a 4 x 3 arrangement as shown in the figure at right. The upper 4 pins (RB7-RB4) are set as inputs, and the lower 4 pins (RB3-RB0) as outputs. One of the nice features of the 16C84 PIC are the internal pull up resistors which can be set on pin by pin basis. This further reduces the component count. The MCLR pin is not used, and is held high. The unit is powered from a 9volt PP3 NICAD battery. The internal discharge current of the battery is higher than the standby current drawn by the circuit.
I have used the 16C84 in all of my projects to date, however, before long they will become obsolete. They are being replaced by the 16F84 which is almost identical. The only difference as far as this project is concerned is the Power On Reset fuse. This is inverted with respect to the 16C84 (nobody knows why). So when programming a 16F84 this fuse needs to be turned ON.
Software DescriptionThe present software uses 176 bytes out of 1024 bytes available within the 16C84 PIC, so there is a lot of room left for expansion. The program was developed in a modular form for easier development and debugging. The majority of the program consists of subroutines called from the main routine.
Referring to the .asm file. A graphical description of the RF envelope follows the header information. The include file "p16c84.inc" is now called. Note: You will have to modify this line to reflect the path to this file on your system. If you are using a PIC programmer that will accept it, the Fuses statement sets up:
All equates for memory variables and assignments are then made. The program then jumps to the init procedure. Although interrupts are unused in the program the interrupt vector is also pointed to this routine just in case.
This routine sets RA0 as an output, and sets it low. Serial data is sent to the RF TX module from this pin. PORTB is configured with RB4-RB7 as inputs with the internal weak pull-ups enabled. These inputs are connected to the ROWS on the keypad. RB0-RB3 are defined as outputs, and are connected to the keypad COLS. The COLS, TX and DEV flags are set low, and the RB change interrupt is enabled.
This short routine, which runs continually, contains calls to the major subroutines. The first subroutine is keywait.
To save battery power the PIC is put into a standby condition using the sleep instruction. The unit then consumes approximately 60uA. Any key press will cause a RB change interrupt to be generated and the PIC wakes up. It would be possible to uses this interrupt directly in the program, however it was chosen instead to mask the column inputs to check if a key had been pressed, and if so, return.
All mechanical switches electrical contacts "bounce" before settling down. The keypad used had a bounce specification of 5mS, however I decided to give it plenty of time so 50mS was chosen. This is the first use of the delays subroutine. This subroutine gives precise delays of multiples of 0.5mS determined by PIC instruction cycles, which are related to the 4MHz Xtal clock. To get a specific delay the W reg is loaded with the number of 0.5mS delays required and the delays subroutine called. So to get 50mS delay a value of 100 decimal is loaded into W.
This routine determines what key has been pressed. This is achieved by sequencing a low on the keyboard COLS, and looking at the ROW response. The variable KEYVAL is a counter, initially loaded with a count of 3. This represents the number of keypad columns. By increasing this number a greater number of COLS can be accommodated Note: As RB0 is not used, the sequence starts by setting COL2 low. KEYVAL is decremented until a ROW input is found to be low. The ROW position is added to KEYVAL to give the value of the key pressed. With a 4 x 3 keypad this is in the range 1 to 12. Keys 0 and 9 are not used, so if detected they are ignored. The * key is used for device OFF, if it is detected then the DEVFLAG is cleared. The # key is used for device ON, if it is detected then the DEVFLAG is set. If either key is detected the TXFLAG is set to show that a data string should be output. Finally a key conversion is performed to return the unit/function binary strings. This is done in the subroutine at keycon. The result, which is stored in KEYSTORE is the unit and function string. For example Key 4 will store 11000111 in KEYSTORE. Only keys numbers 1-8 are converted, however the program can be extended to cope with more keys.
This subroutine is used to assemble and output the 4 bytes that comprise the RF to X10 data string. First the TXFLAG is tested, if cleared then the output routine is skipped, else, the following is sent in order after calling the appropriate subroutine :- preamble - the preamble (8mS High, 4mS Low). houseaddr - the house address byte and its complement. unitfunc - the unit and function byte and its complement. tx1 - a "fudge" bit, as mentioned earlier (33rd "1"). gap - 40mS intercharacter gap. The DEVFLAG is checked and if ON the UNITFUNC is adjusted to set bit 5 of the UNITFUNC byte ON. This bit switches the device ON or OFF.
Because of hardware limitations, I decided to hardcode the House Address into the unit. You can select the house code you want by removing the ";" from the line. The others must have the REM character ";" left in place. To select units 1-8 or 9-16 similar changes should be made within the houseunits routine. The house code set up in the assembler file is "E".
The W reg contains a data byte to be output. This subroutine takes each bit in turn and if it is a "0" calls tx1 then tx0 to output a 10. If it is a "1" then it calls tx1 to output only a 1.
Using delays generates 0.5mS High then 0.5mS Low
Using delays generates 1mS Low
The final subroutine checks to see if any key is still pressed. If they are then the data frame is repeated. If not, then the interrupt is cleared and re-enabled. ConclusionsAlthough this is a rather simple application, the software scheme employed can be extended to cover all house and unit codes. Additional functions such as dim can be easily added. Future units could provide a useful interface into X10 from a variety of devices.
After reading this, Dave Houston commented:For anyone skilled with PIC programming, it should be fairly
simple to reverse the approach and create an all-housecode transceiver using a TW523 (or
better a CM11A) as the power-line interface. Receivers cost a bit more,
|
|
|
| |
|
| |
|
|