There’s an old saying (usually attributed to Mark Twain) that goes: “Everybody talks about the weather, but nobody does anything about it.” There’s a lot of truth in that statement and companies like AcuRite sell a lot of weather stations to people who want to monitor it themselves. What is nice is that they also sell the wireless sensors separately so it’s easy to make your own setup on the cheap. If you really want to do it on the cheap you could just see if you can pick up signals from your neighbors’ sensors. In this post I will show you how to do all of that and throw in the capability to log the data as well.
The RF module I use for this project is the RXB6. It is a super heterodyne receiver as opposed to the less desirable super regenerative receivers. If you look at the cheap RF modules out there you will find that transmitter and receiver boards are often bundled together. Most of those bundled receivers are super regenerative types so they tend to have much lower performance characteristics (including range) than super heterodyne receivers. We only need the receiver module for this project because we will be getting signals from existing transmitters.
Unlike the HC-12 used in an earlier project, the RXB6 does not come with an antenna. Fortunately, it is easy to make your own. In fact, a breadboard jumper cable could be slipped onto the antenna pin of the module if you don’t want to get too fancy. Ideally, a straight wire antenna would be 1/4 wavelength which works out to about 6.8 inches. I initially did the jumper wire thing and had no problem picking up outside sensors even though my electronics workshop is in my basement.
Another possibility is to make your own helical antenna similar to the one that comes with the HC-12 module. There are a variety of plans for that on the web but the one shown in the picture above is what I made. I used some solid core wire (leave the insulation on, except for the tip) from a scrap piece of Ethernet cable and wound it around the smooth shank of a 5/32 inch drill bit. You will need 20 turns. You could also use a 7/32 inch drill bit and wrap 17 turns instead. I’ve attached a PDF file I found for yet another method of making an antenna. Any of these will probably work just fine for the ranges you are likely to have for your sensors. The real key is having a good RF receiver to begin with. The sensors also have pretty strong transmitters.
RF Communication Protocols
There are a few different modulation techniques for transmitting data but these sensors use the simplest which is OOK (on-off-keying) or ASK (amplitude-shift-keying). Since we are dealing with 0/1 data bits in this example, the amplitude is full on or full off. So, for our purposes, OOK and ASK are the same because OOK means the RF carrier is either full on or full off. In that respect, it is basically the same as what we discussed in earlier Episodes about IR encoding. The primary difference is that the carrier frequency for IR is typically 38-kHz while these RF modules use 315-MHz or 433-MHz for the carrier. But, like the IR receiver, the receivers decode the signal into digital-compatible bits.
The HC-12 used for an earlier project follows the standard RS-232 format but these modules do not have a defined format. In essence, they can use pretty much any transmission rate, any bit formatting style, and any message length. The biggest downside is that there are all kinds of transmission formats floating around so the software needs to be tuned to filter for just what you want to use. The 433-MHz band is jammed full of transmissions for things like smart meters, etc., and they use a wide variety of message formats – most of which are proprietary. I was amazed at all the different patterns I saw when monitoring with my oscilloscope. It was kind of like the first time I looked at a drop of swamp water through a microscope.
The weather sensor used here is from AcuRite and sends temperature and humidity information every 16 seconds. On the back it shows a model number of 000592TXR but it is typically advertised as model 06002M. This sensor is used by a lot of different weather station models so it is easy to find and I was able to get them on ebay for under $14/each. AcuRite sells similar looking modules for some other weather stations but they may or may not adhere to the same communication protocol. There is some indication on the web that the 00606 temperature only sensor does use the same message format but with an invalid humidity byte. I know that I am able to pick up a neighbor’s sensor that is temperature only but I’m not sure exactly where it is coming from so I can’t check the model number. If I asked around they might look at me like I was trying to steal their cable service.
As seen in the first waveform shown above, the weather messages are sent out in bursts with a 2ms gap between successive messages. The second waveform shown above expands part of one message in order to see the bit durations and patterns. There are four start bits that are about 600us high followed by about 600us low. The data bits are represented by a 400us high followed by a 200us low (1) or a 200us high followed by a 400us low (0).
The message format consists of 7 bytes of data. The first two bytes are the sensor ID and these do not change (i.e.: it does not use a rolling code). The last byte is a simple additive checksum of the first six bytes. The third byte is a battery level indicator and should always be 44 hex if the battery is good. The fourth byte is the humidity and it is an unscaled value between 0 and 99. It is important to keep in mind that the MSB of bytes 4, 5, and 6 are parity bits and not part of the measurement values. Bytes 4 and 5 are the scaled temperature (Centigrade) with the lower 4 bits of byte 5 being concatenated with the lower 7 bits of byte 6 to form an 11-bit value. The temperature is always represented as a positive number and only becomes negative when the scaling is applied. The scaling is: (C / 10) – 100. The divide by 10 is required because the temperature resolution is in tenths of a degree. The subtraction of 100 is required because 100 is added by the sensor in order to keep the reported value positive.
The schematic is shown above and includes the connections for an optional 1602 LCD. The LCD is optional because you may want to use the circuit strictly as a data logger in which case the LCD is not needed. That would also free up some extra I/O pins if you want to add functionality. The switch input selects between raw data output (14 ASCII characters) or converted data output. The converted output is in the format: HH% / CC.C / FF.F.
There are a couple of defines in the first part of the software that may need adjustment for your application. First, the software is set up so that you can use either the LCD or the serial port as the only output, or use both. If you are just wanting to display data from the two sensors, then you could comment out the define “Add_Serial”. Likewise, if you are only interested in data logging you could comment out the define “Add_LCD”. If doesn’t hurt anything to leave them both active. The other defines you will need to change are for “Sensor1” and “Sensor2”. Those defines need to match the first byte of each of your two sensors. That makes sure that you are only displaying humidity and temperature for your own sensors. When the raw data mode is selected, the sensor IDs are ignored and all valid messages are output. That lets you see any other similar sensors that may be in your receiving range. When you first start out, you will want to use the raw data mode so you can verify the correct IDs for your sensors. If you want to display humidity and temperature from more than two sensors you can change the 1602 LCD to a 1604 and tweak the code to allow for up to four sensors.
The baseline for the software came from a mash up of my IR detector software and my ultrasonic detector software. I wanted to use the 16-bit Timer1 to count the pulse durations but I also needed to make sure that it only counted during the low level part of each pulse. That meant that I needed to use the T1G (Timer1 Gate) input of the PIC. I also wanted to check on the pulse counts when they completed so I used the INT (external interrupt) input and set it to trigger on a rising edge. The bit value (0/1) is determined by the duration of the high part of each pulse but we actually measure the low part because we also want to measure the low level time between data messages.
The interrupt handler determines if the captured count is long enough to be a sync pulse. As mentioned earlier, the gap between multiple message outputs is 2ms so that is what the software looks for. Only the upper 8 bits of the Timer1 count are used (to simplify the software). Because of all the 433-MHz traffic, the initial screening in the software makes sure that the measured time is not greater than 3ms. After the sync is detected the software starts looking for the start bits (600us) and counts to make sure that four ones are received. Once these tests are passed, the software looks for the proper bit times of 200us and 400us.
Received bits are formed into bytes and each byte is saved. After seven bytes are received the message checksum is verified before further processing is allowed. If raw bytes are to be output, then the bytes are converted to ASCII characters and sent out to the LCD and/or serial port. If humidity and temperature outputs are desired, then the appropriate conversion and display routines are called. If you only want Centigrade then you can comment out the calls for the Fahrenheit processing. If you only want Fahrenheit then you can comment out the Centigrade display routine but the Centigrade conversion routine still needs to be called.
Because we are using assembly language we don’t have the built in math routines of higher level languages like C. We could add math libraries but that would be overkill for the level and amount of math required here. For the Centigrade conversion the divide by 10 is done by simple repetitive subtraction to produce decimal values (tens, ones, decimal). The subtraction of 100 is handled so that the result is always positive and negative results are indicated by a sign flag. That means that we need to first determine the order of subtraction, either 100-C or C-100.
Fahrenheit conversion is a bit trickier because we need to multiply the Centigrade value by 1.8 and then add 32. The multiply is avoided by using three lookup tables that convert each portion of the Centigrade value to the equivalent pieces of Fahrenheit. The results from the three lookups are summed and then decimal adjusted. The addition of 32 would appear to be straight forward but it is complicated by the need to handle negative values. As in the Centigrade routine, all Fahrenheit results are kept positive and a sign flag is used. To make this possible the software first looks at the Centigrade sign flag. If Centigrade is positive, then a simple addition of 32 is performed. If Centigrade is negative, then a subtraction of 32 is performed. Again, the order of subtraction is determined so that the result remains positive.
The software monitors the battery status byte (Byte3) and displays a message if it indicates a low battery. This message overwrites all other data for that sensor. There aren’t enough character locations on each line of the 1602 display to allow a battery status symbol unless only one version of temperature is displayed. Changing to a 2004 LCD would allow for up to four lines of sensor data and a spot for battery status on each line.
The software is set up to output the converted data as packed ASCII characters via the serial output of the PIC. When in the temperature mode, the serial output will also include the sensor number (1/2) to facilitate the sorting process. You can use whatever method you want to capture the bytes for display or logging. I use the Windows terminal program Tera Term and connect to the PC using a standard USB to TTL cable. The software baud rate is set to 9600 in the software. You will want to set Tera Term to do a new line whenever a carriage return is received because that’s what the software sends. To do that, go to Setup/Terminal and select “AUTO” for the receive New-Line. To do the logging, go to File/Log. When the window pops up select the location and file name for the log file. Make sure to add “.txt” to the file name to force it to be a text file.
After you have collected the data you can use Microsoft Excel to sort and plot it. To import it into Excel, just click on “Data/From Text”. In the pop-up window specify the file and then specify that the data uses spaces as delimiters. Column “D” should be the sensor number so a little cell formula can be used to sort the data into different columns for the two sensors.
The formula is: =if($D1=1, $A1,NA())
That will copy sensor 1 humidity data to the new column and put #N/A in cells for sensor 2. Change “$A1” to $B1” to copy the Centigrade data or to “$C1” to copy the Fahrenheit data. Change the “$D1=1” to “$D1=2” to copy sensor 2 data instead. That will produce columns for each sensor that can be plotted in Excel. Make sure to copy and paste the formula to every cell in the new column that will receive the sorted data.
Here are some example displays for the LCD and for the Tera Term data logging. That’s it for this post. Check out my other electronics projects.