By Don Carveth, June 2002
Features
Other photos:
Transmitter board..... Transmitter Board In Use..... Receiver Board .....Receiver Board in Use .....Board Underside
Schematics:
Transmitter Board Schematic..... Receiver Board Schematic
Software (Zip files):
C Programs .....PC Software .... Eagle Schematics
Data Collection
The AT90S4433 has six 10 bit A/D inputs. I utilize all six. When the uC "wakes up" from idle mode, it turns the ADC module on, turns on the voltage divider power, waits 100 milliseconds and then reads the six ports. Each raw value is conditioned and converted to an 8 bit value for transmission.
Temperature is sensed using a 10K nominal thermistor. Thermistors change resistance with temperature so a resistor / thermistor bridge with a fixed 8K resistor was used. Thermistors have a large resistance change over the 32 to 200 F range I was interested in but the resistance vs. Temperature curve is logarithmic, not linear. I used a look-up table to linearize the signal and return a value directly in degrees F. Along the way I did discover that there is really no such thing as a standard "10K nominal" thermistor. Get a curve for the device you buy or you will have to calibrate it yourself.
Light is sensed with a Cadmium Sulphide photocell which also changes resistance, this time with light. I set up a divider with a 2K resistor. The reading swings from 4 or 5 in near dark to 251 in bright sunshine.
Battery voltage is sensed with a resistor divider connected directly to the battery. I installed a 5.1 V Zener on the input "just in case". The signal is conditioned to return a value in tenths of a volt, i.e. 12 volts reads as 120. I could see that battery life could become a big issue, even with a device that normally draws only 10mA. A standard 800 mAh NiCad AA cell would theoretically last 80 hours. That's only three days. I decided to use a 4600 Ah lithium laptop battery I had available. Its been running two weeks now and has dropped from 12.1 to 11.4 volts. Should still have two weeks left.
Here is what I see on my PC:
The Radios
I used the TXM-433 transmitter and SILRX-433 receiver from Radiometrix. These are capable of operation at 4800 baud. I purchased these a couple years ago but there are now lower cost modules and higher speed modules available for the same price that I would consider. Here is the result of some research on sources of low cost RF modules. I have not used any of these and cannot vouch for their performance.
The receiving end takes more work, both physically and on the software side. If you are connecting to a PC then you must convert the signal from the RF receiver module to RS-232 using a MAX233 or equivalent. I have a two way set up configured which involves a transmitter and considerably more control complexity. Locate the receiver a ways away from your PC. I located mine outside by a corner of the house and find it works well with the transmitter all over the yard and all over the house.
If you fire up the receiver with no transmitter in operation and take a look at the serial port with a program such as HyperTerminal, you will see a barrage of strange characters. When the transmitter is activated, the receiver "syncs" with the transmitter and much of the noise disappears. So far so good. The problem is that we don't want the transmitter powered up all the time - it would use far too much power. So when we power it down the garbage returns. Our little tidbits of data get lost in a sea of noise. This situation also exists when doing two way commuication. I attempted to use the CD (carrier detect) to determine if a valid signal had been received but I could not get it working properly. The PC program as supplied does not use CD.
The PC must, therefore, filter out the noise. The VBasic software reads every byte that is received, looking for a valid packet. The "Mailbox" protocol is designed to be simple yet robust enough that only valid data gets through. Each packet is formatted as "UUUUU ::AaDdDdDdDdDd...Xx". The "U"s are 1010 characters that aid the receiver in synchronizing. The "::" are the start bytes. Until "::" is read, no data is passed. The receiver must know the length of the incoming packet. Once a valid packet is identified bytes are read until this length is reached, then a checksum byte is compared.
Another issue arising from the need to stay synchronized is that characters with long periods without changes, like 0 or 0xFF, can cause the receiver to lose sync. Radiometrics recommends using "5050" characters only - characters with a balance of ones and zeroes. This pretty well kills an 8 bit protocol. Instead I convert to ASCII Hex, then to 5050. ASCII Hex converts the transmitted byte to two characters, i.e. the number 168, which is equivalent to 0xA8 hex, is converted to "A" followed by "8". "A" and "8" are in turn converted to 5050 before transmission and converted back at the other end. The PC software abandons any packet that contains non-5050 characters.
The Aa and Dd in the packet thus represent the two bytes of the address (ID) and the data. Xx represents the two bytes of the checksum.
At this point it has operated for two weeks, transmitting every half hour and I have not yet seen a bad packet get through. Line of site it may miss a packet a day. If the transmitter is located behind a building it may miss 25%. Because of the reflections it is difficult to predict performance. Sometimes moving the transmitter (or receiver) just a few feet will make a significant difference.
The MicroController
I selected an Atmel AT90S4433 - has enough flash (4K), enough RAM(128 bytes) and has 6 A/D inputs, all in a 28 pin narrow package. The RAM turned out to be a bit tight due to the comm buffers and look-up tables - more on this later. I selected the lowest frequency crystal I had on hand, 4 MHz. I plan to try a 500KHz ceramic resonator to see if it lowers power consumption significantly.
As mentioned above, the uC normally is in an "idle" state. In "idle", the clock still operates but the rest of the uC is shut down. The clock must run as it is used to calculate the transmit interval.
The long delay is generated using the method discussed in Atmel's app note (#1268). The TCNT1 (16 bit T/C) output compare is physically tied to an input configured as the clock source for TCNT0 (8 bit T/C). This effectively results in a 24 bit counter, adjustable by the value stored in the TCNT1 output compare register. With a 4 MHz crystal, this gives delays up to 2 hours.
When TCNT0 reaches the overflow point an ISR is triggered which performs all the duties. Once the ISR is complete the program returns to the main loop where the sleep instruction is executed, putting the device back into "idle".
On reset the uC is initialized - all ports are configured as required, unused pins are configured as inputs with internal pullups, the Mailbox interface routines are initialized and the UART set up. The Send rate DIP switch is read and a single packet is transmitted.
The main routine is called GetAndSend(). It turns on the sensor power, the A/D and the LED, waits for 100 ms, reads the ADC inputs, turns the sensor power, A/D and LED off, then transmits the data packet.
The Mailbox system architecture is multiple master/single slave with the data originating on the slave. I refer to it as multiport/multiprotocol serial RAM and is also applicable for uC to uC communications. The master is normally reading from specific locations in the slave, i.e. the address. It can be configured such that the master, in this case the PC, can also receive fixed length, unsolicited data packets from a slave. The routines used here, contained in mbRFslv.c and mbRFslv.h, are a subset of the complete two way comm software. The slave does not wait for a request but simply transmits its data packet as desired.
The SendMaster() routine loads the six data bytes into the comm buffer and calls SendToMaster(), defind in mbRFslv.c. The address must match whatever is configured at the PC end. SendToMaster adds the sync characters and the "::" start characters. Note that the send routine is not the usual write to the UART then wait till done. The send routine writes a byte then returns to the main routine. As each byte has been transmitted, a UART buffer empty ISR is run which transmits the next character. This method is not really required in this application but is necessary where the Mailbox routines exist within a busy application. Since I had operable, tested code I used it.
I did run into difficulties with the available RAM (128 bytes). GCC stores an initialized constant array in flash and RAM. There is no built-in facility to tell it to store the array in flash only. I had lookup tables for the thermistor curve and for the 5050 conversion. Along with the comm buffers this was rapidly using up my available RAM. I was able to find some routines in the progmem header that allowed the array to be designated as type prog_char. Data can be read from the table using the PRG_RDB macro. This was not ideal but worked satisfactorily. I was able to get this working for single bytes but not for integers. Other compilers apparently have a "flash" data type that accomplishes what I was looking for. It seems to me that the keyword "const" should direct the compiler to store only in flash.
The GCC source code is attached.
Construction
I like wire-wrap for one-off type projects such as this. I can wire-wrap a board like this in a couple hours. I find it to be highly reliable and changes can be made fairly easily. I now use a ground and power copper strip that I solder to - I find this goes a little quicker and results in a better power distribution system. I mounted the transmitter board directly on the lithium battery - makes a nice, tidy package. The board has an on-board 5V 78L05 regulator which is powered by the lithium batteries 9 to 12 volts. This could be made more efficient with an LDO regulator and lower voltage battery. The antenna is just a length of copper wire. The length is important - make sure it matches the quarter wave frequency of your transmitter/receiver. Check the documentation that comes with your RF modules.
The transmitter schematic and the PC Interface Board schematic were prepared using Eagle 4. Both the Eagle file, with my library, and a .gif file are included.
The PC End
This article is primarily about the transmitter. I will discuss the receiving end software in enough detail to allow one to get the system operational.
The Mailbox software is a Windows based object written in Visual Basic 5.0. It's basic purpose is to read from and write to slave Mailbox uCs using either an RF 5050 protocol (as used in this article) or an 8 bit protocol intended for hardwired applications. The program runs as an Active-X .exe server, which means it can operate standalone, or be called as a reference by another Windows application. The Windows application can request variables (bytes or 16 bit ints supported) from specific Mailbox addresses in the slave or send variables to specific addresses. The Mailbox software handles all of the packetizing, noise filtration, variable parsing, buffering activities.
The Mailbox software can also run in standalone mode. It will then startup with the main monitor screen active. This will allow you to send and receive data packets to/from specific addresses and monitor all incoming/outgoing data traffic. A data scroll screen is also included to watch the data progress over time.
The software needs to be installed like any other Windows application. The Mailbox.exe file will be installed in your Windows\System directory. You can run the program directly or it can be referenced as a component by another program. Also included are the source and executable files for MBTest, a simple program for testing Mailbox as an ActiveX server. The compatibility of this software has not been widely tested, but it does run on my two PCs.
The receiver board consists of the receiver module and an RS-232 level converter (MAX233). The board in the photos has both a receiver and transmitter and is set up for two way communications. Only the receiver is required for this application. I installed the board under a plastic weather guard with just the antenna poking through. I ran an RS-232 cable and a power wire from the PC to the receiver board. At the low baud rates used here you could likely run 100' or more without problems. The receiver definitely works better when it is distanced from the PC.
Debugging
Debugging comm systems is always a challenge. There are many links in the chain and any one failure will bring the whole train to a halt. I recommend starting with a stripped down system - no radios, connect the transmitter directly to the PC port. You will need a CMOS to RS-232 level converter - I have one built into a serial cord - it's ideal for this type of testing. Set the send rate at a fast interval, like once a second. If you have HyperTerminal or the Mailbox software running you should see a series of characters that looks like UUUU*ccDdDdDdDdXx once every second. If Mailbox is configured properly it should accept the packet and update the parsed data registers and the data scroll. If this is not working, try enabling the print_info() routine inside of main() and disable the Mailbox send routines.
If you have got this far its time to introduce the radios. Start with the radios together in the same room. I recommend having an oscilloscope on hand to monitor action at the various pins. If it doesn't work recheck all your connections. I always like to have two of every component so I can check for functionality. Check for comm activity at the transmitter module data in pin and at the receiver module data out. Check if power is applied. Remember that power is disconnected at the transmitter until the transmit ISR is activated.
Operation
Now you can sit back and enjoy the excitement of watching real time data pour in. I set my transmitter up to send every half hour. It is connected to my spare PC, an old 233MMX, which perks along at about 18% load. I plan to try it on an even older 66MHz unit just for grins (and less power consumption). And now I can get back to the robot. Next project is a handheld communicator, with voice recognition, to converse with the robot, using the same RF methodology.
If you have any questions about the article, please contact
the author at don@botgoodies.com.