Raspberry Pi reading WH1081 weather sensors using an RFM01 and RFM12b

This article describes using an RFM01 or RFM12b FSK RF transceiver with a Raspberry Pi to receive sensor data from a Fine Offset WH1080 or WH1081 (specifically a Maplin N96GY) weather station’s RF transmitter.

I originally used the RFM12b, simply because I had one to hand, but later found that the RFM01 appears to work far better – the noise immunity and the range of the RFM01 in OOK mode is noticeably better. They’re pin compatible, but the SPI registers differ between the modules, in terms of both register-address and function.

This project is changing to be microcontroller based, and using an AM receiver module (Aurel RX-4MM5) – a much more effective approach – arduino-yun-reading-wh1080-using-aurel-rx-4mm5. Currently testing on Arduino Yun, but will probably move to a more platform agnostic design to support Dragino and Carambola etc.

The weather station comprises an LCD display and a mast of sensors. The LCD display also incorporates temperature and humidity sensors for indoor readings, as well as a barometric pressure sensor. The mast contains sensors for temperature, humidity, wind-speed, wind-direction, and rainfall, and transmits data-packets using a 433MHz transmitter. It’s the data from the mast that this project is focused on, along with the addition of a Bosch BMP085 I2C module to get barometric pressure.

There are variants of the Fine Offset WH1080 with transmitters of differing types (e.g. different frequency, modulation, or both), so while this project will apply in principle to similar devices with different branding, in practice some tweaking may be required.

For anyone who already has a rough idea of what’s required, and just wants a quick overview for some pointers, I’ve presented a summary first below.

Wiring the Module

Note: the revision 2 boards affect this project in two ways. First, if you’re using the BMP085 pressure sensor, then you’ll need to address I2C-1 rather than I2c-0. Changing the base address of the I2C peripheral in the code should be all that’s required. Second, the GPIO pin on header P1-13 is now GPIO27 rather than GPIO21. Again, the code will need simple modifications. I’ll incorporate these into the code in future, but until then you’ll have to figure out where the changes go if you want to build this on Rev-2. Email me if you need help.

Pin connections from the RFM01 (and RFM12B) to the Raspberry Pi are as follows. You may choose to add current limiting resistors. Pull ups may be required for SDO and SDI (I’ve never found a definitive specification for SPI – it works with them, and it probably works without them too): –

I used a breadboard to wire this up, and unsurprisingly found this to be far from ideal with the RFM12b module. At close range, the receiver works very reliably, but as the signal weakens, noise often drowns it out (even just leaning close to the circuit, or moving a component).

A breadboard is fine to test the SPI stuff, and also works well when the transmitter is in close range, but to test the receiver properly, etching a PCB (or even just wiring the bits together) would be a better idea.

Wired in the noisy breadboard

I decided to wire the RFM12b to a 26-pin female header to avoid breadboard noise, but discovered that the Pi was generating enough of noise of its own, and having the module (more accurately, the antenna) so close to the Pi was affecting reception. A long ribbon cable improved things, as did a length of coax to move the antenna away from the rest of the electronics.

When I switched in the RFM01 (after carelessly frying my RFM12b), the situation seemed much better, and the device worked more reliably than the RFM12b did in exactly the same environment.

How it looks before adding the BMP085 barometer module

The RFM01 seems far more immune to noise -it’s wired to a 26-pin header and plugged directly onto the Pi. The antenna is simply a 1/4 wavelength (17.5cm) wire soldered to the module. It receives perfectly even in this harsh environment, possibly in part because it works on the lowest LNA (Low Noise Amplifier) settings.

Any wires near the Pi are capable of generating RF noise, even just a breadboard jumper wire sitting underneath the Pi, or an unshielded Ethernet cable. Be aware of this and keep noise sources out of the way while testing (or wire the antenna on a length of 50Ω coax).

Just connect SDA and SCL along with 3V3 and GND for the BMP085

Received Data

The transmitter sends 11 bytes of data as follows. Some of these differ from any of the documentation I’ve found on Fine Offset weather stations, so I’ve described them here (letters to the nibbles for the description below): –

The nibble ‘q’ is likely to be the low-battery indicator, thanks to Ken McCullagh reporting that his transmitter is now sending a ‘1’ rather than a ‘0’, and his LCD display is also now showing a low-battery symbol.

Nibble ‘m’ is unknown. It may be that the rainfall counter is two whole bytes (time will tell – I may take a watering can to the rain collector), or perhaps it’s the high nibble of either the wind-speed or gust-speed. Between them, nibbles ‘m’ and ‘q’ could provide this extra wind data.

To get temperature, subtract 400 (0x190) and divide the decimal by 10. For example, reading 0x2oe – 0x190 = 0x7e, which is 126. This represents 12.6 degrees C.

To get a wind speed values (in m/s), multiply the value by 0.34 and round the result to one decimal place. So, value 0x04 is round(4 * 0.34) = 1.4 m/s.

For rainfall, as documented elsewhere, multiply by 0.3 to get the recorded rainfall in millimetres. This value is a counter that increments to zero after 0xff (or 0xfff if it turns out that nibble ‘q’ is part of the counter).

Humidity is simply displayed as a decimal, and wind direction ranges from 0 to 15 for N, NNE, NE, ENE, E, etc., as per the LCD display. The checksum is CRC8, and a nicely written function, adapted from the OneWire Arduino Library by Luc Small, is included in the source code to calculate this checksum.

The Code

If you’re using a cross compiler, the you may need to edit the CC variable in ‘Makefile’ to point to your compiler. If you’re using an RFM12b, then edit file ‘rfm01.h’ and change ‘#define RFM01’ to ‘#define RFM12B’.

The program configures the RFM01 using SPI, and then continuously looks for interesting data from the module on the Pi’s GPIO pin, and dumping valid packets to stdout as hex strings. It also decodes the hex-data into more meaningful values, and sends them to stdout as printf() formatted strings.

Note that the calculations on the Raspberry Pi are done using floating-point arithmetic, whereas the WH1080 uses fixed-point. This means that the output may differ slightly between the Pi and the LCD display, because the Pi’s calculations are more accurate. For example, raw wind speed of 0x01 yields 0.34m/s on the Pi, but only 0.3m/s on the WH1080. Converting this to mph yields 0.8 mph on the Pi, and 0.7 mph on the WH1080. Therefore the Raspberry Pi reading is more accurate.

You may notice that the output below also displays barometric pressure and an indoor temperature value. These have come from a Bosch BST-BMP085 Barometric Pressure Sensor via I2C. Wiring the module to the Pi was trivial, since it has the pull-up resistors and bypass capacitors already on-board. Therefore, simply wiring SDA and SCL, along with 3V3 and GND, to the Pi is enough to get this sensor working. If you don’t plan to use one of these, remove the line ‘#define USE_BMP085’ in wh1080_rf.h before compiling.

Only SDA/SCL and 3V3/GND, The other two needn’t be connected.

The output from the software includes a scan of RSSI duty on all amplification levels, RSSI thresholds, and baseband bandwidths. This lets you see where the noise is in your environment so that you can spot likely configuration values that will yield reliable results. I’ve omitted this from the example below for clarity.

The data-bits are the number of bits seen in this packet, including preamble, and the offset is the position of the device-id byte (or zero if it wasn’t found). The short packet count gives an indication of how much noise is being seen as data.

The ‘gap’ value tells us how long it’s been since we’ve seen a valid packet, and the stats show the pulse widths (in microseconds) that the receiver’s demodulator sent to us. The frequency deviation shows the values of the AFC offset registers. The AFC is manually strobed on each successful packet, in order to slew the frequency offsets with frequency drift.

Prior to a reading, the code switches the process to the Kernel’s built-in realtime (SCHED_RR) scheduler policy so as not to miss any bit transitions on the GPIO pin, and this is enough to make the process immune even to heavy workloads. I’ve tried running multiple CPU and IO intensive processes while reading, and didn’t see any packet loss. This may not hold true over time but, if not, there are sysctl parameters for the scheduler that can be altered to improve latency, for example: –

root@pi:~# sysctl kernel.sched_wakeup_granularity_ns=50000

In any case, it should be possible to run weather software and perhaps a web server on the Pi at the same time, while reliably taking RF sensor readings. I haven’t got that far yet.

Note that the transmitter actually sends two packets in succession on every other transmit cycle. It sends a packet, and repeats it 100ms later. I presume this is to increase receive reliability on the LCD display, or perhaps their receiving circuit sometimes fails to set AGC appropriately with a single packet. The code will ignore any subsequent data after receiving a valid packet until the next 48 second gap elapses.

Tuning the RFM01 Settings

The RFM01 configuration will depend on your environment. The following lines of code are most relevant: –

The CMD_CONFIG (the module settings) command includes the receiver bandwidth setting. This can be one of BW_67, BW_134, and BW_200, BW_270, BW_340, and BW_400, and the value determines how sensitive the receiver is, but wider bandwidths mean more susceptibility to noise.

The CMD_RCON (receiver settings) command sets the Low Noise Amplifier setting (LNA_LOW, LNA_MEDIUM, LNA_HIGH, and LNA_MAX), and the RSSI threshold (dBm) at which we consider a signal to be valid. The VDI setting follows RSSI in the above example, because I’m not sure how relevant the other settings are to an OOK signal.

If you launch the program with any parameter, it will enter RSSI mode, which continuously samples DRSSI with the current settings, and reports the duty (percent) of the DRSSI signal from the SPI status register. You can use this to figure out the best combination of settings for your setup.

I find that the lowest total-gain/bandwidth combination that reports a small amount of noise (e.g. < 5%), or that reports zero-noise close to that boundary, gives the best results. If you’re settings are too sensitive, you’ll lose signal strength in the noise. If they’re not sensitive enough, you won’t maximise your potential reception.

For weaker signals/longer ranges, you may have to allow for variations in the environment – heavy rain can affect reception, outside temperature variations will affect the transmitter to some degree.

If the transmitter is close enough to the receiver, most settings that don’t saturate the receiver with noise will work fine, particularly with an RFM01 module.

Oscilloscope and Logic Traces

The output from the transmitter looks like this in my logic analyser: –

Pulses generated at the transmitter.

This is the signal that comes from the the transmitter’s microcontroller to the RF part of the circuit, and is the modulation of the 433MHz carrier. I think this modulation is called RZI PWM (Return to Zero Inverted, Pulse Width Modulation), RZI because the fixed clock-pulse always returns to ‘not-zero’, and PWM because pulse width defines the data bits.

The narrow pulses are binary-one, the wide pulses are binary-zero, and these are interspersed with 1ms clock pulses. The first eight narrow pulses are the 0xff preamble, and the next eight pulses represent the first data byte (always 0xa1, the device id).

When it gets to the DATA pin on the RFM01 receiver, the signal looks something like this:-

Pulses seen from the RFM01 DATA pin

Note that it can now be seen as RTZ PWM (Return To Zero, Pulse Width Modulation) because the clock-pulse is now inverted (i.e. at zero) and the data pulses are at 3V3. Again, it’s the pulse-width that determines the data (and hence why this isn’t actually an OOK signal, and why the RF modules are being used out of specification).

This oscilloscope output is what our software is sampling via the GPIO pin. It samples hi-low transitions, recorded as pulse-width in microseconds, into a buffer that gets filled until a gap of 5ms is seen (or 500 points maximum, in which case we’re very unlikely to have valid data).

The software could be far more efficient and elegant – there’s really no need for a buffer to scan into, as it can all be done in realtime as it arrives. However capture-and-process is easier to experiment with and study, particularly when you have to wait 48 seconds for the next wave of bits.

Other Notes

You can play with the internal pull-up and pull-down resistors on GPIO pins using Gordon Henderson’s GPIO Utility. I have a compiled binary of this here (link) – make sure it’s executable (‘chmod a+x gpio’), and copy it to ‘/usr/local/bin/’.

However, by most accounts no pull-ups should be needed in this project, and any that are can be provided by the internal weak resistors already on the GPIO lines. If I used them in my wiring, it’s only because it was easier to pop one in the breadboard than it would have been to write code to configure them (before I found Gordon’s utility).

The RFM01 is accessed using the SPI kernel driver. Therefore the modules spi_bcm2708 and spidev should be loaded. If not, then you’ll get the error “can’t open device”. To load them, run ‘modprobe spi_bcm2708’ and then ‘modprobe spidev’ – use sudo if you’re not root.

The RSSI will vary by environment – even the location of the Pi, and the antenna’s orientation to the Pi can make a noticeable difference with a weak signal and high-gain/low RSSI threshold parameters.

In the output of the software line with ‘Short’ in it means “short packets seen” – there should be zero in a quiet environment, but one or two are quite possible. If you’re getting lots of short packets reported, then you’re probably picking up noise, because your receiver configuration is too sensitive.

The code has a few lines specifically for the configuration of the receiver – the LNA and RSSI threshold values, and also the bandwidth values are the most important ones.

The table of data that shows on startup shows the noise sampled for each combination of these values. The columns, though they’re not labelled, are noise for the different bandwidth settings of the RFM01 (e.g. how far above & below the centre frequency the receiver should listen for a signal).

You need to look at the table and pick some settings that have zero noise, but are close to settings that do have noise (e.g. we’re looking for a setting that’s sensitive enough to hear the signal, but not so sensitive that any background RF is picked up as data.

Next Steps

There are a number of things I want to do in this project: –

Integrate the decoded values into some open source weather software so that it’s usable from the Internet (probably wview).

Rewrite the code to improve the structure and make it more readable (the current version was only a tool for experimentation).

Add some heuristics to the software for auto-tuning of receiver parameters.

References

RFM01 Datasheet – from the HopeRF site. The title is ‘RFM01 Universal ISM Band FSK Receiver’ should you need to search for it because of a broken link.

JeeLabs RFM12B Command Calculator – a useful client-side browser application to calculate register settings using form inputs and selections. Only a few apply to the RFM01 (e.g. frequency, AFC, and data-rate).

Strobotics RFM12 Tutorials – a good, though micro-controller centric, description of the RFM12B. Much of the information also relates, broadly at least, to the RFM01.

WH1080 EEPROM Data Definition – document detailing the memory organisation of the LCD display unit. This differs to some extent from that of the Maplin device, but there are enough clues in it to make it useful.

Raspberry Pi Forum Thread – discussion on this topic, includes information on hardware variations that others have tried with varying levels of success.

Hi Kevin
I’m a retired production sound mixer and I have a ‘retirement project’ in France.
Sounds far grander than it really is. Lots of remedial work to be done, and I mean lots!
What I’d like to do is do some research on wind amounts and speeds with a view of going installing a wind turbine and generating my own electricity.
I need to make sure I’ve got enough wind over a period of time, and will give me an indication of what power I can hopefully get.
I did electronics earlier in my career but I am rather rusty now, but I can still solder!
The Raspberry Pi answers my questions as to how to read the weather information back here in the UK from France. I’m right at the end of the telephone line, and am just within reach of broadband – just- 512K and no more. I jut need a way of ‘seeing’ the data without spending a fortune on a weather station with internet capability.
So the Maplin £59.99 offering looked just the ticket so I bought one and so far it looks perfectly good for my ‘project’.
I have a couple of questions if you don’t mind.
Simple one first, where did you get your 26 way female header? I’ve looked on Farnell’s site, where I’ll get the RFM01 but can’t see any at a ‘sensible’ price.
Do you have a schematic of the connections from the RFM01 to the GUIO pins?
i.e. which connection goes where.
I’ve set up the Raspberry Pi with Tightvncsever and will be looking at Apache as well.
If you can help I’d be very grateful as my electronics is very rusty and somewhat out of date! I’m learning Linux which coming from a Mac orientated background isn’t too difficult. Code writing is NOT my strong point though!
Many thanks in advance,
Ian

I didn’t draw a schematic because it’s little more than wiring to the SPI pins (and I2C if a pressure transducer is included), but you should be able to sketch it out easily enough from the pin mappings in the post. I may do a schematic in the future (mainly because I want to CNC mill a PCB), but I can’t say when.

Hi Gordon, yes – the pull-ups would typically go from the RPi header pin to 3V3. However, looking around the net, most people say that pull-ups are not needed for SPI. I don’t know enough about the bus to say for sure. No harm having them, but perhaps no need either.

More generally, there’s a Raspberry Pi forum thread (http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=9563&hilit=pywws) that discusses weather station software, and I recall that someone got pywws working. The author of that software mentioned that live-logging can leave the WH1080 in an indeterminate state periodically, but that longer logging intervals (e.g. hourly etc.) seems stable.

I had looked to integrate my RF reader with pywws, but it appears very tightly bound to the USB interface. It looks non-trivial to make it work with live 48-second intervals, and I had more interesting things to do. However, if you do make your own reader, then contact me for any changes I might have made since (assuming I haven’t posted updates here).

Thanks for that, my Pi is happily logging the data using pywws from the USB interface, however it is well known that the USB Interface (not the PI one!) from the display is somewhat unreliable and will freeze for no apparent reason which means that you have to pull the batteries and lose the data stored in the display.

The WH1080 has both indoor and outdoor humidity (nibbles ‘gh’ described above), so you could forget about the the extra sensor.

The two humidity sensors tally when I have the transmitter indoors, and my Bosch BMP085 tallies with the LCD display’s barometric pressure, so I’ve been pleasantly surprised with the Fine Offset sensors.

I believe the usb problems associated with the pi and this weather station are all related to pywws and using LiveLog.py . Congratulations on your ambition for creating your own receiver but an easier workaround to get you up and running quickly in the meantime is to use Hourly.py and run it every 5 minutes.

This is a fantastic article… i was midflow of trying to decode the signal when i stumbled across this site.

I have RPi running pywss livelog.py… and get the random crashes… I want to use this technique to get rid of the usb interface too.

I have also an alternative solution which was my fall back if i fail to get this solutionworking.

GPIO controlled relay that resets the power to USB when it crashes…
– USB Screen running without batteries
– USB plugged into external board with a relay on the +5v…
– GPIO 3.3v controlling the relay to reset…

Alter the pywss livelog.py code to handle USBException… and just turn pwoeroff to weather station… and then continue!

You could possibly just use a MOSFET to drive the +5V to the USB, and save the hassle and power requirements of a relay. See the power-controller article I’m currently writing for a suitable FET that switches at 1V and has a very low Rds. I’m driving it directly with a 3V3 PIC, and the Pi works fine even with a borderline PSU, so it should easily work for the weather station’s LCD unit.

The Maplin part A59JN is the same one I used – there are other UK suppliers of this module who resell it under different names (e.g. RF Solutions ALPHA-RX433S).

I bought the barometer module from eBay seller ‘bionicbot’ (http://www.ebay.co.uk/itm/320939715020), but yes – any BMP085 module that exposes the the I2C SDA/SCL pins and operates at 3V3 would work.

I think that the code is up to date as I write this. It still needs work, like parameterising the altitude for barometric pressure calculations, and almost certainly writing the data to an SQL database (I think SQLite, to give more control over how tables relate to SD card files).

I’m also considering adding an LCD display, buttons, and perhaps an real-time clock, so that it can operate entirely on just a power connection. Ultimately I might end up with a PCB to hold everything neatly.

Thanks for the writeup Kevin, your instructions have been brilliant, and I’ve just received my barometer chip (also picked up an indoor humidity sensor to play with as well, since the head unit has both indoor and outdoor humidity.

I’ve got it interfacing with pywws processing and plotting – I made your code store the data in the same format as pywws expects, and then I removed the bit from the pywws code where it tries to use the USB to interact with the headunit and just takes the data which I’ve stored – currently using the Hourly.py script, even though I’m essentially livelogging at 48 seconds.

Couple of things I still want to do: I want to make it wifi, but have ran into issues with my RALink micro USB dongle and a cheap 7 port powered hub – the hub I think causes the pi/ethernet/wifi to hang up regularly, a real PITA. Ultimately I want this to have this as an autonomous unit in the spare bedroom, wifi connected to the web. Obviously still have to add in the barometer and humidity. I assembled it all on a stripboard and have ribbon connectors, so will add it to these.

Also still need to make the code slightly more robust – will need to add a timeout to send a reset command if it doesn’t get a transmission in a 60 second window or something. And will hopefully put the code up in github or something….

Great news Ken, particularly about pywws – I tried and failed to get live-data working, so gave up after that – but the live-data could be handled independently (e.g. a static page generated for Apache to serve) to complement the hourly feed that you’re pushing to pywws.

I haven’t found the need to do a chip reset – certainly not for a missed transmission (I had used hardware and software resets while testing with the RFM12B, but they never solved any of the problems I was having). However, the whole main loop does need to be broken into functional chunks to allow, among other things, timeouts to be handled elegantly.

There are plenty improvements we could make to the code, so perhaps we should make it a shared effort.

Yeah no bother collaborating, not sure how much time i’ll get to spend on it but sure every little helps! I’ve started to restructure the files into a more generic structure, will upload it to a github soon

Hi Mark; yes assuming you’re using an RFM01, bit 12 is correct for the band (giving 10 in bits 12 and 11).

The frequency register will also need to be set. The datasheet gives the calculation, the result of which should be set in the code where ‘cmd_freq’ is defined. It’s best to find the exact frequency of your transmitter (433.92MHz is a very common centre-frequency for devices working in the 433MHz band, I suspect there’ll be a similar favourite for 868MHz devices).

Off hand, I think the calculation expressed for F (which is the value you set in the register) is F = ((f0 / (10 * c1)) – c2) * 4000. e.g. for f0 exactly 433.92MHz I used F = ((433.92 / (10 * 1)) – 43) * 4000 which gives 1568 or 620h. The c1 and c2 values are 1 and 43 for 433MHz configs, 2 and 43 for 868MHz configs.

Other than that, I guess the code will work as-is. Don’t trust my algebra, I think it’s correct but the datasheet is definitely correct.

The table of RSSI readings that’s displayed on startup is intended to help you pick Low Noise Amplifier (LNA) and RSSI threshold settings, and a also bandwidth setting. If you’re seeing near 100% even for LNA_0,RSSI_73 on the lowest baseband bandwidth (first column – 67KHz), then something’s amiss.

Things I’d try: –

1. Dump the other bits of the status register from the RFM01 to check they’re sensible (e.g. I’d temporarily hack strobe_afc() to dump the ‘status’ variable then call in main() and exit). This should confirm that your SPI communications are working correctly.

2. Use the gpio utility from WiringPi (https://projects.drogon.net/raspberry-pi/wiringpi/the-gpio-utility/) to make the pull-down resistor active on GPIO21 (the DATA input we’re sampling). I’m not sure how crucial this is, I have an external pull-up but I think the RFM01 is driving this pin high or low at all times regardless. It occurred to me that the DATA pin is irrelevant – the RSSI duty is read from the RFM01’s status register.

3. Unwire the antenna and see if the RSSI drops mostly to zero (as it should). If so, check you’re using a 17.5cm wire, and ideally locate it a good few inches (at least) from the Pi. For testing, I used a long ribbon cable and also a length of coax – with similar results for both.

Note the copper pad on the RFM01 that the antenna connects to can be quite fragile, so don’t let any heavy wires pull at the solder joint, or the copper might come away – recoverable, but best avoided.

A quick way to tell if you have a pull-up/down resistor already active is to use my gpfsel utility (see other blog post) to dump the state of the pins and then touch your finger on the pin and see if it changes. A floating (tri-state) input pin will jump between high and low if your finger goes near it. If it remains constant ‘low’, likely the pull-down resistor is active, and with a constant ‘high’ then the pull-up is active.

Doh! I had reversed SDO/SDI, the RSSI values now look sensible, just trying to find a signal. I expect the data packet to be longer as my transmitter has a DCF clock receiver, nothing consistent found yet, but I’ll move the Pi closer to the transmitter tomorrow.

One thought on your rainfall reading and checking the high nibble – just swap your wind/rain cables around, you soon clock up hundreds/thousands of rain ‘tips’.

Great – if you’re picking an LNA/RSSI/Bandwidth config combination, look for settings showing zero near some noise – you’re looking for a ‘sweet spot’ that’s sensitive to signals, but not to noise. I did most of my initial development with the transmitter unit right beside the Pi, leaving little chance of noise or other transmitters bleeding over the signal.

It’ll be interesting to see how the DCF stuff is transmitted – if it’s an independent follow-on packet, then the code should work without modification – it looks for around (or exactly, I forget) 88 bits. If you need to hack the code to look for a DCF packet, bear in mind that I look for the 8-bit preamble before considering a packet to be present. This should be disabled if you just want to dump anything returned by the receiver.

Thanks for the tip, someone suggested the very same on the Sandaysoft forum, and it’s on my todo list when I get time.

I don’t think so, not yet. There’s a lot of variability ‘under the hood’ between devices that otherwise look very similar. The 868 and 915 MHz units that I’ve seen so far appear to be using a different modulation scheme (FSK) to the Maplin unit that I have. Progress is being made though, follow the Raspberry Pi Forum thread here http://www.raspberrypi.org/phpBB3/viewtopic.php?p=266777#p266777

I also experience freezing of the usb using pywws livedata(). The only solution when this happens seams to unplug the batteries 🙁
My project is a meteo telephone answering machine for HangGliding and Paragliding (www.vololiberomontecucco.it) so the station will be installed remotely ( on top of a mountain ) and freezing is a big problem.

Just ordered a RFM01 and will try it. My questions :

– To you ( or some body ) has a version of the code for 868MHz and RPI Rev 2 ?
– My project is in python. Did somebody bing the code to python ( ctypes,swig ,cython … )

There are some pointers in the comments on getting this to work with 868 MHz, and the Rev 2 board should just need the code to use GPIO 27 rather than GPIO 21 (see first paragraph in Wiring section of post). I’ve just received a couple of Rev 2 boards, so I’ll doubtless make changes and commit new code before too long.

There’s no Python code for this, and I’m sure it would be too slow to sample the DATA pin of the RFM01 module. I have an esoteric idea about doing it using a DMA trick which would free up the processor (and allow slower languages to be used), but it’s too much effort for too little gain at the moment. I’d be happy to share the idea by email with anyone not scared off by the DMA section of the datasheet.

Ken McCullagh has had some success with getting data into pywws, though with some caveats I think.

The best approach to my mind is to keep the C code to harvest the data, and then shell to whatever language you care to use for processing (e.g. into MySQL or SQLite database or, as Ken does, into pywws).

Just cmd_rcon – the RSSI threshold and LNA should be chosen according to your environment (I added a couple of paragraphs with notes on interpreting the table of numbers that show on startup).

As an aside, I recommend you disconnect the sensors and bring the transmitter unit indoors to the computer – from experience, it will take less time to unscrew the unit from the mast than it will to investigate the unknowns caused by a weak signal/poor soldering/ineffective antenna/noise from the Pi/etc.

If it’s beside you, then the signal will be as good as it gets and will shout over most interference. You’ll also be able to see the LED come on when the transmitter is sending. You could probably also dump output from sample_rssi() in a tight loop to see it spike when a signal is seen.

Hi Kevin, I am a newby to and can’t seem to get any of this to work. When you say “If you’re using a cross compiler, the you may need to edit the CC variable in ‘Makefile’ to point to your compiler. If you’re using an RFM12b, then edit file ‘rfm01.h’ and change ‘#define RFM01′ to ‘#define RFM12B’.: Please explain. Do I need to compile this (how?) or should it just unpack and run.? Do I need to remove all of the ‘#’ symbols from this file to select the different devices?

sorry it seems so basic to you but I need the blindingly obvious spelt out please.
regards
Ken

You’ll need to compile the code, and you’ll also need to edit a few variables to configure the receiver for your particular environment. You should use the ‘gcc’ compiler that’s part of Raspbian – I mentioned cross-compilers because some people like to do their development on a separate computer, and then run the executable on the Raspberry Pi (this is cross-compiling).

The # symbol is the character that introduces pre-compiler directives in C. They’re not comments like you might see in bash or Perl, etc.

Note that there’s an issue with the code’s use of a specific transmitter-id value – it turns out that this value can change, so I need to modify the code. Someone (another Ken) has done this on his version of the software, see the Raspberry Pi forum for a link to his GitHub repository which may have this modification. Also, if you have a V2 Raspberry Pi, then the I2C port and GPIO pin have changed – simple enough changes, but it requires you to read the code and modify accordingly.

You might want to practise compiling some ‘hello world’ stuff in C before embarking on this project. I think it’s a bit ambitious to try without understanding at least the basics of C (in other words, don’t be too disheartened if you struggle at first).

I updated the code to handle changing station-ids. This was highlighted by Ken McCullagh, whereby when batteries are changed, the station-id also changes. This could easily prevent packets being recognised. The new code looks for 0xfa rather than 0xa1. The ‘f’ nibble is part of the packet preamble, and the ‘a’ nibble appears to be constant in all valid packets.

These are defined as LNA_LOW/MEDIUM/HIGH/MAX for the RFM12B, which I changed after switching to the RFM01 (I recommend you use this instead). I’m about to remove the RFM12B code, since I no longer have one to test against. You should be able to fix up anomalies easily enough if you want to proceed with the RFM12B – the register arrangement is slightly different, but not by much.

Hi,
I really need this but have the same problem. Searching the file I could only find LNA_0 to change to LNA_LOW but the others are not there even though they error, plus there is one that doesn’t fit called LNA_XX. I know you say you don’t have ability to test but please help with solution.

Kevin, sorry to be a pain, but I am unsure which lines to change in wh1080_rf.c to change the GPIO to 27 for the REV 2 board. Can you post the changes here we need to do please?
I am all connected up eith nowhere to go!
Excellent project and want to say thanks for all your hard work thats gone ito it!
Dicky

There’s also the line ‘*(gpio.addr + 2) = (*(gpio.addr + 2) & 0xfffffe07)|(0x001 << 6)' that sets pins up for input or output. However the pins should default to Input mode anyway, and the other pin that's referenced in the code was only used by me when debugging (to reset the module, and later to drive an LED).
Therefore I think that line could be ignored/removed/corrected as you see fit. Personally, I'd recommend reworking it to set just GPIO 27 to an input (just in case it's been left as an output by another program). If nothing else, it would be a useful exercise to understand how the FSELn registers work.
Also, note that if you're driving any I2C modules (e.g. I include a barometer), then the I2C address has changed from BSC0 to BSC1 that's now routed to header P1.

I have successfully got the RFM01 working with the Rev.2 board (need to improve my antenna though). However, I am struggling to get the Bosch humidity sensor working. I have changed the memory address for the BSC0 define to point to BSC1, and also changed the line that configures GPIO0/1 as ALT0 functions to configure GPIO2/3 instead. All the data values I get from the device are zero. I have checked the SDA and SCL lines with a meter and they both sit at +3V3 so are being pulled up correctly. Is there something else I might have missed?

I’d first try lsmod to make sure that neither ‘i2c-bcm2708’ nor ‘i2c-dev’ are loaded, since we access the hardware directly for I2C stuff. Although I’ve not had problems hitting the hardware with kernel drivers loaded, it’s probably not a good idea.

Also double-check you’ve wired SDA and SCL correctly. Beyond this, assuming you don’t have any digital analyser available, you could place the I2C read call into a continuous loop and watch for voltage fluctuations with a voltmeter.

Another possibility for testing would be to wire up SDA and/or SCL to a GPIO configured as input (hence high impedance) and to sample the GPIO pin during I2C transactions. I haven’t ever done this, but it could act something like a logic analyser. Since you’re only watching for transitions, only a small amount of data need be held, and it could be relatively easily deciphered.

If you’re using current-limiting resistors on the I2C lines, then check that their values aren’t too high.

Lastly, double check the BSC1 address – I assume you defined it in the header from 0x205000 to 0x804000 (yielding effective address of 0x20804000).

SDA and SCL are wired correctly and there are no current limiting resistors in the lines.

I am using
#define BSC0_BASE (IOBASE + 0x804000)
for the peripheral address.

Unfortunately I don’t have access to a scope or logic analyser, but putting a meter on both the SDA and SCL lines indicates that there is no activity. I would expect my meter to flicker a bit, but it sits at a solid 3.307V for both lines (fluctuating by 0.001 occasionally).

To me it looks like the SDA and SCL lines are not being driven through the software.

Yes, looks fine to me – multiply the original values by 0x40 (e.g. << 6) which gives the numbers you've used.
It would be interesting to see if, after using the kernel's I2C driver, the code now works (e.g. the BSC1 peripheral has now been properly configured by the driver).

Thanks very much for your quick reply. I am not a ‘C’ pprogrammer and I did see that line and knew it had to be changed but didnt think it was a simple as changing 21 to 27 – perhaps I should have just tried it!
But the other thing was the setting of the pin as an input (which I don’t understand how that line works) as leaving that line would still try and set GPIO 21 as an input which is now not available on the rev 2 board of course.
Yes, saw the LED code there so might try usng that to tell me when I have recieved data.
I am not using the barometer yet so have commented that out as specified above.
So I will try this out again tonight!
Again, sorry to bother you on this and thanks for your post – HAppy New Year!

The dots indicate short packets – that means, some data on RF but not enough to be considered a candidate weather-station packet. You’ll see a couple of lines in the code where LNA, RSSI, and Bandwidth are configured – these are the central parameters in setting the receiver sensitivity. Bring your transmitter (the long grey box) beside the Pi to get the strongest signal – always a good place to start. You’re looking for settings that are appropriate for the signal strength – it’s a bit of an art! Note LNA_0 is highest amplification.

Been mostly a software guy, so getting my head around this hardware 🙂 As far as I can tell:

Bandwidth – in Oz, so 433mhz, so that shouldn’t change, should it?
LNA – Low-noise amplification – 0 is highest as u mentioned. Does highest amplification also mean most noise? This is the 0, 6 etc numbers right?
RSSI – not 100% sure but these are the numbers 86, 91, 97, 103 etc. Some sort of intermediate freq?

Like other examples I’ve seen in this thread and the rPi forum, all RSSI 103 seems to be at 100%, while other values seem to change as you run at diff times.

To get the best results, do I just start at one end, and change numbers to see what yields results? Tried a number of values, but still only got a single dot once, then nothing else no matter how long it runs. Is there some way I can dump data packets to make sure the RFM01 is picking up data?

I was also thinking of adding a full 69cm antennae which should pick up the full wavelength?

Will def be blogging my learnings for hardware n00bs as love the tech, just getting my head around many new principles 🙂

LNA – any noise does get amplified along with the signal, but an LNA is designed to minimise this. So, if you can reliably receive at lower amplification, then your noise immunity should generally be better.

The bandwidth setting is a margin above and below the configured frequency of the device (e.g. 433.92MHz + any auto-frequency offset) within which the receiver will look for a signal. Again, too wide and it may pick up unwanted signals, too narrow and it might miss data packets (e.g. altered transmitted frequency due to temperature coefficient of the electronics, or humid atmosphere, etc.).

I’ve hopped over here from the RPi site thread (chsims1 over there). Quick recap: 868.3MHz transmitter, rev 2 board, not seeing transmitter signals. I am using the Maplin A62JN, which I am assuming is the same as the Hope RFM01. I am getting short packet dots when near obvious noise, but do not see anything elsewhere at 48s intervals. What do you see as a good method of problem solving here …. Maplin do not provide a datasheet for their A62JN, which worries me that I can’t check connections, wiring is always problematic, and the difference in frequency band and rev board all make me think extra possible problems. I take on board your passing parameters to wh1080_rf to do continuous RSSI scanning, but I am beginning to think the problem is further up the line.

Oh btw, just to show what a novice I am, I hadn’t shortened my antenna for 868MHz! At least, that is one thing ruled out now.

Your write-up here is very much appreciated, and I hope that you feel you can keep up with the “poor fools” trying to emulate your exploits,

So, assuming you have the transmitter close by, I’d drop the LNA to -20 or -14, the RSSI to something like -73 or -79 and the bandwidth to 67kHz. Not much noise will get through those settings, but the signal will.

You could add an ‘if > 0.0 then print “Got something”‘ inside the bit of code that loops continuously sampling DRSSI (the bit inside ‘if(argc > 1)’), or better still dump the time of, or interval since, the last RSSI spike. Leave for five minutes and see what comes up.

The Maplin module really is just an RFM01 – it’s not even re-badged. So the datasheet I’ve included in the references has all the info you need.

You may need to do what I did originally – that is, open both the transmitter and the receiver (get some photos) and see if there’s anything to learn there. My concern with an 868MHz unit is that the RF part could be completely different – that is, perhaps it’s using FSK rather than OOK/PWM. If this is the case, it would need some rework to get working (but would probably give you more resilient comms, over longer distances).

I’m happy to help you work through this one if you’re eager to fathom it out – the forum topic or email would probably be the best place to discuss (we run out of indentation here!). Close-up photos of inside your transmitter and LCD display will tell us a lot.

I still cannot get anything from my 868MHz box either. Now I do have a spare ‘faulty’ transmitter. It appears to work apart from no RF.

If (big if?) the fault is purely on the RF side, I’m wondering if I can tap into the data lines on this transmitter and snoop the firstly the configuration data (if it is using an on-board RFM unit) and the data packets.

I have no ‘scope, would a sound card OSC be any use? or even patch through to the Pi GPIO pins directly?

Yes, I’m convinced it’s possible to tap into the PCB to get the data, and transmit it yourself (it was my original intention). Maybe you could post photos of your transmitter (and, if possible, the LCD display) internals first to the forum.

Panalyzer might be worth trying for a protocol analyser. I don’t know much about soundcard scopes – I’d guess they’re fine for low bitrate stuff, but rubbish for 8MHz SPI, for example.

I have downloaded a PDF if u let me know yr email address. I’ve also updated your code and included a few things:

1) Saving the data out into a comma delimited file in /tmp
2) Doing a HTTP get with the data so I can remotely log the data to a web server
3) Added a sample_frequency variable – logging data every 48 seconds is quite granular, so this just logs/posts the data every X polls.

Happy to share the minor changes… I plan on plotting the data on the server for real time web data. Just doing some custom ASP.NET MVC bits to keep it simple. I also want to poll other devices on 433mhz, so will prob look to spinning off threads for each device to share the code for a number of different devices/crc’s etc…

One more thing – I didn’t use any resistors and it worked fine. I’ve had trouble picking up the signal once I placed the unit back outside, but I think I fried my antennae connection, so I’ve ordered a new RFM01 so I can test.

It’s likely you’ll need to find new settings when you move the unit – you need to choose settings that match the signal present at the point of reception, so a significant increase in the distance between the units will need different settings (lower RSSI threshold, wider bandwidth, higher amplification, or any combination). I moved the transmitter (or the Pi, I forget) in stages of around 10 metres at a time to keep a hold of the signal.

Thank you for posting this project! Although I have slightly different plans, I still have a Raspberry Pi that I would like to interface to a RFM transceiver module. With your recipe and information I think I can hit the ground running!

Hi, I have this setup running now for two months and receive two different weather stations from the neighborhood, presumably Alecto WS4000’s, at 868MHz.

Frequency 868.300-868.500MHz, but with signal voids around 868.420MHz, so be careful here. Optimal results at 868.360-868.380MHz, LNA=0, RSSI=103, BW=134.

There is an additional bonus on those stations. They have a DCF77 receiver, which can be received with a small mod to the code. It appears that the third nibble (first two are the 0xFF preamble), is a message type. Normally this is 0xA for sensor readings, but it is 0xB for time readings. So adding to the detection byte 0xFA, a test on 0xFB, I recieve time signals as well.

Those time signals are transmitted at the same 48sec interval, but at the start of each even hour. E.g. at 21:59, the normal transmission stop. It is quite for three minutes, and then 4-5 repetations of time signal occur with 48 sec interval, after which normal sensor data transmission is resumed.

One more remark:
Ever since I updated to the latest raspbian 3.6.11+ #371, the code hangs frequently on the raspberry pi. This is avoided by increasing the usleep(5) at the end of the signal loop to usleep(25). It does not harm reception, and the raspberry remains more responsive.

Looks ok to me – the table shows noise levels being received nearby for each combination of configuration values. You need to choose a combination that suits your own environment (e.g. amplified enough to pick up your signal, but not so much it’s drowned out by noise). You need to edit a couple of lines of code to set your chosen configuration values (LNA, RSSI threshold, and band width).

See the blog article, previous comments, and the forum thread mentioned above for more details if needed.

Thanks, I have it working, I am getting sensible measurement values but I’m not sure what values I need to edit, it has just worked. Are the LNA, RSSI threshold, and band width just added as arguments on the command line when running the sudo ./wh1080_rf, I have printed out your code and I am wading my way through it ;).
Thanks for your hard work much appreciated. I don’t really want to use the supplied Maplin display for real data capture, its more of a vanity thing. I want the Raspberry PI to do all the heavy lifting and will use your code as a base.
Regards
-Jim

Hi Jim, The pulse stats say how wide the margin is for received pulses, above and below the threshold. A good signal will have threshold near 1000 (microseconds), and high/low pulses will be around 500 and 1500 microseconds respectively (I may have them the wrong way round, you might want to check). Typically, wider the margins mean a less reliably signal, so the information can be used to choose receiver settings, for example.

Hi, Very useful information, thanks very much. Just to let you know that I have your code working with the Maplins WH1050 weather station. This is the “little brother” to the WH1080 and doesn’t have the wind direction indicator, and there is no USB output on the receiver unit.
Only minor changes were required to your code. Mainly due to the fact that the WH1050 1 less byte. There was also a problem that the bitstream was offset by 1 bit, this was handled by changing:
“uint8_t bit = rssitime_buf[packet_offset + 1 + (idx * 8 + b)]”
and by adding an extra bit to the end of the stream.
After this, all the results match the LCD display (discarding wind direction), even the CRC is OK.
Thanks again for your great work

My initial thoughts would be to sample the RSSI into a buffer and try to visualise the hi/lo transitions (e.g. process them into a spreadsheet) to figure out if the signal is meaningful. You might expect to see some preamble, followed by data, and then perhaps a checksum.

Using RSSI is really only feasible for OOK signals – that is, signals where the RF is on/off to signify hi/lo. For FSK, where the signal alternates between frequencies, it wouldn’t be feasible to discern data from the RSSI.

Note that digital RSSI over the SPI bus may not be fast enough to get all necessary transitions. I had trouble getting reliable readings from an RFM12B using digital RSSI from the status word. I don’t know about the RFM22B.

I’m assuming you’re working with a Raspberry Pi. If you’re reading RSSI using a register, then SPI may be a bottleneck, especially if you’re going through the operating system to read/write the SPI bus. I don’t know much about the RFM22B, but there may also be a delay in the module sampling the Analogue RSSI.

You may be able to get the Digital RSSI after setting a threshold to eliminate noise. This would then become a matter of reading a flag from the status register which may be faster than reading an arbitrary register.

You might consider reading an analogue RSSI value directly from the RFM22B, in which case you’d need extra circuitry to convert to a digital RSSI (e.g. a comparitor with an adjustable threshold).

However, 98ms is really quite high. None of the above could account for such a discrepancy in my opinion, particularly if the code is in C. You might want to check that there’s no blocking code in the sampling loop – it needs to be as simple as possible. Also, check that no applications are hogging the CPU (run console only, not X).

Great project. Your code is the closest I could find to tackle what I want to accomplish. I am trying to use a 433.92 Mhz receiver (i.e. this: https://duckduckgo.com/?q=AK-R03A) to receive and decode the chatter of my external temp sensor(s). What do I need to change if there is just one data GPIO pin that I am interested in? Or am I on the wrong track here?

In the existing code, there is essentially only one data GPIO pin that we’re interested in, leaving out the SPI and I2C stuff. It should already be quite close to what you need to experiment with.

I don’t have any experience of the receiver you mentioned, but in your situation I’d be looking to sample the RXD pin transitions on a GPIO and store them alongside a timestamp in order to graph them (e.g dump to CSV and import to a spreadsheet). You may need a big buffer if you’re unable to trigger a transmission on demand.

Another option would be to use ‘panalyser’ to snapshot the pin data (I haven’t followed the development of this, but it seemed usable when I last read up on it). In any case, you should be able to show whether or not the module is capable of providing the GPIO with suitable data to work with.

Hi All
Need some help, pls….. I wanna build a receiver with rfm01 and attiny13 / 45. I try use ook mode, but not skill for write this soft for avr. The rf module is 868mhz. Like this self tuning, self gaining software. Can somebody help for me? Thx for ALL 🙂

The send_command16() is used to send the ‘cmd_’ variables to the transceiver. The variables are defined together, near the top of the source file ‘wh1080_rf.c’. This is typically where you would change the radio parameters.

If you follow the thread(s) on the Raspberry Pi forum, I think you’ll find others who have received FSK transmissions – it’s something of a simplification, since you can use the FIFO rather than having to sample the data pin.

The later posts on the forum topic (http://www.raspberrypi.org/phpBB3/viewtopic.php?p=152023#p152023) discuss using a FIFO – these relate to the receiver operating in FSK mode. I think your options are to sample the DATA pin with FIFO off (wired as you suggest, perhaps also using DCLK), or else to read the FIFO buffer using SPI. I’d suggest sampling the DATA pin, initially at least – it’s easier to observe what the radio is receiving without the extra layer of the FIFO (e.g. try graphing the output in Gnumeric).

I have been using your code, slightly modified for the wh1050, for some time now but I get some unusual hangs. Every so often, usually after a period between 24 and 48 hours, no data is received and the Pi stays in RealTime scheduler mode until data is finally received. The odd thing is that on the last 5 occasions (at least) the delay waiting for the data is 4368secs. Is there anything significant about 4368?
I have tried to add checks to the main loop in the code so that the Pi returns to Standard scheduler after 120 secs, but it would appear that it never gets to the bottom of the loop when waiting for the data.
When I added the check to the “for(idx=0; idx < count; idx++) {" loop the Pi appears to hang if the 120sec time out is exceeded. I can ping the Pi, but cannot SSH in. The Pi never recovers from this.
Any ideas? The Pi is only about 5 meters from the transmitter.
Many Thanks
Bob

Make sure there’s a sleep somewhere in your loop – I don’t have the code in front of me right now, but I’m sure we yield to the OS periodically – if this isn’t happening, then I can see how SSH would become unresponsive.

Yes, I do have a sleep (two in fact), in my loop. I can’t imagine what would be interfering, especially as the problem does not occur at set intervals.
I cannot see where your code yields to the OS, but I am not very familiar with “C”. I was brought up on COBOL (yes, I am that old) and have quite a lot of experience with VBScripting.
I will try not running in Realtime at all, but I do use the Pi as a web server to display the weather information, an dI would also like to add some 1-wire probes (and possibly the pressure sensor). That is why I was trying to release the Realtime after a wait of 2+ minutes.
I will let you know if it works.
Thanks again
Bob

Hi, I wonder if it’s caused by the microsecond timer overflowing? This would occur after roughly 4294 seconds. If there’s an error causing the code to hang on the timer, where the exit case only occurs after an overflow (e.g. after returning to zero), then it could account for most of the 4368s delay.

It might be worth adding that I think it unlikely to be hardware related – it’s either software failing to sample the data, or the receiver not getting (or not interpreting) the RF signal correctly.

If this is the source of the problem, then we may need to throw away any timer reads that deviate too much from expected values. Since the CPU is running at 700MHz it shouldn’t interfere with readings, which are measured on a 1MHz timer.

I’ll probably have a look at the existing code when I get a chance, in light of the link that you gave. It could explain some of the drop-out anomalies that I’ve seen and put down to RF issues (though the link mentions interrupts, which we’re not making use of, so maybe a ‘red-herring’).

Hi,
I’m using this code in a simulation of a Kopp Free control transmitter to generate timeouts between transmission blocks (up to 5,5 sec, RaspberryPi and RFM12b Module). It was also expected by me that &0xffffffff is not needed, but I’m not a “C” expert. I had also effects with timer overrun, after using code above it runs fine even if the timer generates an overrun. But of course the code is only fine if the timeout itself is below 1/2 of the max timer value (@32 bit timer and 1µsec timer resolution < 2147sec)

Hi Kevin,I have purchased the smartalpha 868Mhz module and the evaluation board. I was hoping having bought the evaluation board it would make it relatively easy for me to interface my windows pc with the module. My initial aim is simple, just to be able to make the module transmit and receive. I downloaded the software utility which RF Solutions supply. This allows me to configure the baud rate, frequency etc of the module, but that is as far as I’ve got. I have sent a number of emails to RF Solutions re how do I get the unit to receive or transmit but the emails I receive assume a knowledge that I don’t have. I was hoping that I could use something like Hyperterminal to send commands to it via USB to get it to transmit and receive. I guess my question to you is, is there an easy way to talk to the unit using a piece of existing windows software, or should I give up now before I tear all my hair out?

If the device is not in configuration mode, then it’s in transmit/receive mode, in which case all data sent via the serial port is sent over the air. However, it work in packets, where Hyperterminal works in streams of single characters. If you can get RTS/CTS to work appropriately (hardware handshaking) via Hyperterminal, you might get somewhere sending packets with only ASCII characters.

My modules have older firmware that didn’t handle handshaking properly. This seems to have been addressed in later versions, but I haven’t used any of these, so I can’t really say much more. I think, even if you get some communications working, you’d be coercing both the module and Hyperterminal into doing things they weren’t really designed for – fine if you enjoy experimenting and hacking, but not if you want something that just works.

Hi Kevin.
I have to say that after I came across with this blog entry, I’ve immediately bought a some rfm01s and 2 of those sensors from maplin.

I’m a rpi / cubieboard and home automation enthusiastic, and I’ve already installed a lightwave rf inline relay next to my drayton lp522 boiler/ heating control. (The lp522 can turn on and off the heating 3 times a day)
using the inline relay I can now control the heating from both smartphone and from crontab (after sniffing the packets sent by the smartphone and replicating it)

I’ve seen in your later posts that you’ve lost interest on raspberry pi. I’m really sad to read that but I’m still hoping if you could spend just a little effort on this project because I’m looking to integrate this along with my rf heating control, but this code doesn’t work very well. I’ve added some timestamps to the code, and considering I’m using 2 maplin heat sensors I’ve dropped the 48 second sleep as well. As descripbed above I’m also experiencing that the code locks up for 4200ish seconds. I also noticed that the sw clock on the raspbian also gets skewed. I’m not too much concerned on this, but is there any way to fix these 1 hour+ lags to achieve constantly reliable temperature monitoring somehow ?

Just to follow up my own comment, I’ve found that in “wh1080_rf.c”
If I comment the following line:
usleep(5); // No point running with nanosecond loops when pulses are in the hundreds of microseconds…

It will no longer stop receiving signals and also the clock remains in sync as well.
The only problem from comment the line above is it will constantly try to read signals without any delay, and it will render the PI almost completely useless for anything else. the wh1080 process with go up 99% cpu and the pi wil lag big time as well over ssh, but at least the weather readings are reliable.

Hi Istvan, bear in mind that the 48 second sleep time relates to the transmit interval of the weather station that the code was designed to work with – it’s tied quite closely to this hardware, but of course if you leave out the sleep intervals and simply dedicate 100% CPU to reading RF signals, then it can be used to read from other devices too.

Hi Kevin,
thanks a lot for your wh1080_rf project.
I reused your code to emulate a “Kopp Free Control” home automation transmitter within an FHEM home automation setup.
After I found your web page I suddenly ordered a RFM12b module and mounted this module to my RaspberryPi.
After modifieng your code (GPIO’s etc.) I was able to record the Kopp transmitter signals via RFM12b’s “FSK/DATA/nFFS” pin via Oscilloscope.
With this data I could calculate the baudrate (about 4,8 kBaud), afterwards I was able to receive the transmitters data in Fifo mode and decode the messages.
As a next step I was able to send this data also and use the whole stuff within FHEM to switch on/off the Kopp home automation moduls.
Everthing works fine, now.
I started about 4 weeks ago and I would need about half an year without your wh1080_rf project.
I posted my work here:http://forum.fhem.de/index.php?topic=14790.0
but its in German language (I’m sure you will understand/recognize the attached modified code)

So again, thanks for your really good project which was easy to understand and a big support for my own project.
Claus

It’s a lot more reliable and dependable than I ever achieved with a Raspberry Pi – WiFi is stable and with a receiver such as the AUREL RX-4MM5 (Farnell 169-9487), it reads reliably over decent distances. Cheaper super-regen receivers also work well, but with less sensitivity.

My sketch just reads the data and dumps it to the console, the idea being that the Linux side of the Yun can do the decoding and posting/hosting of the data. Much more like I’d originally wanted, thanks to the dedicated MCU of the Arduino Yun.

Good to hear it’s stable Andy. What distance is there between your transmitter and receiver? I’ve had my doubts about long-term use of these FSK receivers for anything other than the strongest of signals.

Beautifully done – if you want to work with me on an AM/PIC receiver version (we could interface the entire thing with I2C or UART to the RPI, but it would work with SBCs too), then I’d write some appropriate firmware etc. You might have noted from another post – this is a rock-solid way of getting RF signals into an SBC – nothing missed, and the possibility of grabbing all sorts of other data from the airwaves at the same time.

To use the code on any other SoC, you would need to rewrite a lot of the set-up code – the hardware registers and their associated memory map will be different.

The UV index and light intensity data are documented elsewhere on the web, as I recall, but the packet format can vary between seemingly similar devices, so you may need to just capture some data and try to make sense of it. Note that it might be sent less frequently as the other data.

I don’t recommend using an FSK receiver for reading non-FSK signals – this article was an experiment for fun, but not something I made much use of. I pasted some Arduino code in a later post that can read data from an OOK receiver. It works more reliably and consistently.

It’s possible, but very unlikely. To get a signal that’s loud and clear, the configuration parameters need to be set according to your environment. Read the comments here, and follow the Raspberry Pi forum posts to catch up on discussions that were had on this.

All looks good – can’t think why it’s exiting, as I recall it runs on an infinite loop. Did you use a modified version of the code from somewhere else? If so, check the loop logic against the original code you can download from this page.

It’s a little bit messy, since it was only really experimental code, but it should be easy enough to follow – in the loop, we capture some signal, try to make sense of it, repeating until we get something valid. When we do find a valid signal, then we assume the next one will be 48 seconds away, so we sleep for a while.

That’s a bit out of scope really – but there are lots of resources to find on linking, makefiles, and MySQL client libraries. A simple solution would be to write an insert statement to file (temporary ramdisk, to save SD card wear), and do a system(‘cat outfile.sql|mysql myweatherdb’) call, or periodically run a cron job to push accumulated data. It’s not as efficient as a directly linking custom code, but then you have 48 seconds of thumb-twiddling until the next data transmission.

Unfortunately I don’t know anything about signals sent by FSK variants of these weather stations – the code here was written for an OOK signal generated by one particular Fine Offset model (signals can vary between models). To have much hope of getting meaningful data, you’d need to know for sure the way your transmitter modulates the frequency in order to transmit bits. You’d then need to confirm that the bits you receive are valid (e.g. checksum), before figuring out what they actually mean (the structure of the packet).

I want to ask you some advice, I have a weather station WH1080 with package Fowsr (OpenWrt router) to send the data online http://www.wunderground.com. The console is connected to the USB port of the router Huawei HG553. There are tuttazia bug every 1/2 weeks, I have to reset the console because it stops. Now I want to permanently delete the console, take the data from the sensor without external usb console but use the wireless module RFM12B. You can tell if the module RFM12B USB key () also works well on the router USB OpenWRT (connect wireless keyboard to USB port) and take directly the values of the external sensor ??? ***

I don’t know about any RFM12B USB keys, nor about your router. I would recommend you take the Arduino Yun approach that I wrote about here. I don’t think the RFM12B is reliable enough for AM reception, except where the signal strength is consistently high. The AM receiver I mention in my post gives exceptional performance, and the dedicated microcontroller of the Yun gives reliable decoding. It will require some programming effort, since the code I provide only returns the raw bytes from the receiver. These need to be converted into weather information, but the code for the Raspberry Pi version gives you all the necessary calculations.

I think your understanding is incorrect. The RFM01 and RFM12B RF modules both communicate to the host using SPI, not UART. The USB-to-UART module you linked to won’t allow you to talk to the RF module.

Yes, that module might work, in principle at least. If the OOK performance is the same as the RFM12B or RFM01, then it will be unreliable. If the OOK performance has been improved, then it might work well. You will have to do some research and experimentation, and you will almost certainly have to reprogram the microcontroller to perform data-reads from the module – the router is unlikely to have accurate enough timing for reliable reading of the signal pulses.

Only raw data can be received from the transmitter. Please be aware that what you intend to do will require many more steps than you describe above. You may still discover that it does not work, but if so it should still be fun to try.

Yes, all models of the Pi are similar enough that you can use them for this. You need to configure your chosen GPIO pin for input, and check that the code reads from the right register. You would need a true realtime OS to have any chance of reliability. Assuming your WH1081 has an AM OOK transmitter, I’d recommend that you use a proper AM receiver. They require no configuration, and with a realtime OS, should give reliable results. The RFM01 is really designed as an FSK receiver.

Thank you very much for this article. It has allowed me to successfully decode the transmission from my WH1080. There is one small problem though – I cannot get the checksum test to work. I am using your code to calculate CRC8, but it doesn’t agree with the RF packet. I have a theory though – that the checksum algorithm has been changed on later models. This is my third weather station. The outside and inside units of the first two inter-operated with no problem. When I bought the third unit, it did not inter-operate with the previous two. I didn’t know why at the time, but I’m beginning to suspect that some time in 2016 they changed the checksum algorithm. Can anybody confirm this? Does anybody know the new algorithm?

Well – I have cracked it. There is an amazing piece of software at http://reveng.sourceforge.net/. If you give it 4+ examples of complete packets, then it will reverse engineer the algorithm and it’s parameters. In the case of the recent versions of the WH1080 the algorithm is still CRC8, but with parameters init=0xa8, poly=0x31, xorout=0x18. The modified CRC8 code is below. Why would they make this change other than to be difficult?

Thanks for contributing – I hadn’t realised that recent devices used different CRC parameters. I can think of a couple of reasons why they might vary these values – for example, in a dev environment when you want your code to reject irrelevant packets. I imagine the offices at Fine Offset have more than a few transmitting devices on the go at any one time.

Watchman Sonic, I think, uses an FM transmitter. In principle, this would be easier to decode since the RFM12b and RFM01 are really designed for FM signals, and will demodulate the data into the FIFO buffer. However, the chip needs to be set up to receive this signal. I have some vague recollection of this being done and documented elsewhere.

The Watchman Anywhere, as you say, uses the GSM network to send. This means that it’s not really practical to hack this to get your own data. However, since I haven’t seen one of these or taken one apart, I could be wrong – maybe they’re more hackable than I assume. Regardless, it would be a lot simpler (and cheaper) to replace with a transmitter that sends locally.

As an aside, I have a schematic for a tank sensor with a LoRa transmitter that can be built quite cheaply that can send data via home broadband – I haven’t had time to write it up yet, but it will be open source hardware if you have the skills to build it (really just an ultrasonic sensor, an AVR microcontroller, and a LoRa transceiver).