Decoding RF signal from Ambient Weather Thermo-Hygrometer

Alert: Make sure you download the latest one, the earlier version had a tricky bug that I have eliminated
DebugManchester.ino at

Another thing that has come to my attention is that the cheaper 433MHz Rx's have slow AGC and you may find that a stronger TX closer to the RX will cause weaker signals from sensors to be lost as the AGC does not recover in time to give them a fair go (so to speak in ultra scientific lingo!) Try the Dorji line: RF-DRA886RX-S Dorji 443MHZ 107 dBm ASK Receiver, SMD Package

Cheers, Rob

Hello Rob,

Thank you for your invaluable help. Below is my working sketch with commentary in the header. I have had problems with range using my RX so will look into the one you have recommended.

So the next goals are:
Incorporate error checking to remove the 3% of bad readings
Incorporate a warning if a sensor does not communicate for an extended period of time
Stop printing the data twice (is there something really basic I have overlooked?)
Work on negative temperatures
Devise a way to store values and send them only once a minute on the serial (as a precursor to sending updates to a server later on)
Improve the reception range (probably a hardware issue)

Please let me know if you have any comments or suggestions

Andrew

Hi Andrew,

What excellent progress :slight_smile: very good work. Thank you for your comments.

I have a few suggestions to make and maybe answers for some of your questions.

I will email your code back to you. I am just a beginner on GIT-Hub and not confident about the push/pull process. However I won't attach it here and indirectly publish it myself, and you will obviously need to consider what you keep and what you alter.

There was a late edition to the Debug program (won't be the last I am sure!) that concerned checking the first zero and also making sure the header hits had been equaled or exceeded. I have added that in.

if ((!firstZero)&&(headerHits>=headerBits))

It basically forces the header to be valid before the first zero is accepted.

Secondly I have also simplified the idea of how to discard the leading zero and one in a more general way (Thanks to your request :slight_smile: ) track the variable "discards" and you will spot what I have done. However it means the first byte in the manchester[bank][0] array is where to begin for the data ie index=0. You will need to alter your calculations for temp and hum as they will be one byte out now.

I have also added a 1 second interrupt that calls a small routine that can trigger off a 1 minute output of your data. Not original but you will find the acknowledgement in the code.

If you increase the number of bytes required until you stop getting data then you know will have to reduce the maxBytes by one and then you should be looking at all the stable data. If you are getting two quick transmissions of the same packet then you will probably need to store each packet in a separate manchester[bank][byteNos] and then compare them. I have inserted a bank check routine that will check all four banks so feel free to modify that as you need. It may send the packets twice as some form of redundancy and still have a check sum as well. Watch the byte you suspect is the checksum and see what its behaviour is with changing values in the rest of the bytes. The Bios WS sent the packet 4 times as validation check, the Oregon Scientific had a simple arithmetic checksum based on nibbles. Ambient may just rely on a comparison of two packets.

If you intend have multiple sensors each with its own transmitter you will need some way of stopping the output until all of them have registered valid numbers, then after that, send output each minute. Each Tx'er ORing a bit in a byte if successful will allow an easy check. Now that you have a timer in there you can also set up a check for Tx'ers going "quiet" for too long as well.

You will probably need a more generalised way of calculating from the Manchester[bank] the values for the transmitter/sensors so that your output to the server will be more manageable? I think you need to use an array of some sort.

These changes may get rid of the 3% bad readings, especially the validation of course.

The final caveat is all I have done is see if the program with my alterations compiles which is definitely no guarantee it is still working. I am looking forward to see what you do now. I am impressed and feel you are definitely on the homeward stretch to quite a useful package.

Cheers, Rob

Just to let everybody who might be interested know..

My much improved sketch for the arduino and Ambient Weather F007th is available at

There is some error checking which has almost eliminated the number of bad readings (there are exceptionally humidity readings between 100% and 128%).
I have tested the sketch with negative temperatures (using a ziplock bag and my freezer) and negative temperatures appear to register correctly.
The sketch prints the temperature and humidity readings to serial every 5 minutes.

The final stage for me is to get this data uploaded and logged on a website, my adafruit CC3000 breakout is on the way!

Thank you to all the forum members who have helped.

Attached is the final working code.

This accurately captures temperature and humidity data for 6 Ambient Weather F007th sensors and uploads it to Xively every 5 minutes using the Adafruit CC3000.

The code leaves 5 minutes between starting and uploading the first reading - this gives each sensor 5 chances to send in a reading before it becomes a datapoint.

Once the starting temperature and humidity is established the sketch rejects any values where the humidity is outside the range 1-100% OR the humidity is changing at a rate faster than 5% a minute OR the temperature is changing at more than 1.5C per minute.

As as I write this, the sketch has been running smoothly for 5 days without a problem.

Good luck with your own solutions!

F007th_Xively_CC3000.ino (16.9 KB)

First, thank you to those who worked on the F007TH sketch, especially the manchester decoding.
I choose the Ambient for my project since the code existed, but was not happy not being able to verify the checksum. So I've reversed engineered it. The code is below and here is a link to an article on how I tackled it:

I hope that is payback to those who did the heavy lifing on the decoding.

uint8_t Checksum(int length, uint8_t *buff)
{
    uint8_t mask = 0x7C;
    uint8_t checksum = 0x64;
    uint8_t data;
    int byteCnt;	

    for ( byteCnt=0; byteCnt < length; byteCnt++)
    {
    	int bitCnt;
	data = buff[byteCnt];
	
	for ( bitCnt= 7; bitCnt >= 0 ; bitCnt-- )
	{
            uint8_t bit;
			
            // Rotate mask right
	    bit = mask & 1;
	    mask =  (mask >> 1 ) | (mask << 7);
	    if ( bit )
	    {
		mask ^= 0x18;
	    }
			
	    // XOR mask into checksum if data bit is 1			
	    if ( data & 0x80 )
	    {
	    	checksum ^= mask;
            }
	    data <<= 1;	
	}
    }
    return checksum;
}

Congratulations! That was a heroic effort, and begs the question, why did they do it that way?

BTW the code on the web page is screwed up by the html translations of ">" etc.

Yeah, I wondered if this was random, original algorithm or if it is based on some accepted methodology.

Thanks for the note on the web page. I was so focused on the indentation and style I totally missed those &amps!

Some error checking algorithms are actually "forward error correcting", that is, they can be used to correct a limited number of bit errors in a message after it has been received. Hamming codes are an interesting example, where several extra check bits are sent, like 3 extra bits for each set of 4 message bits. This can correct all single bit errors and detect 2 bit errors, but not correct them. See Hamming code - Wikipedia

It is conceivable that this is one of those algorithms, but that is certainly not obvious and in any case, I doubt more than one bit in the entire message could be corrected using a single byte "checksum" like this one.

Excellent work.
Can you share the rest of your code?
Cheers Rob

Would be glad to if you can point me to an easy way of posting the code somewhere. It exceeds the 9K character limit of a post for posting it inline and I haven't tackled using git (I'm still back on Subversion).

Also, is there a way of monitoring a thread? I've marked my replies with "Notify me of replies" but I'm not getting email notifications.

Per robwlakes request, <update: link removed, code is attached in my next reply) It is based on the excellent work of others on the Manchester decoding found in the F007th sketches. Apologies for the changes for style - it is simply personal preference. I also modified it to use arrays rather than 7 scalars. And removed the Wifi and Xively code I wasn't using. I plan to soon combine it with the webserver example via the exec library and serve the sensor values via my Ethernet shield.

Hi, use the Attachments and other options, to attach your sketch.

Tom..... :slight_smile:

Thanks for the pointer. Duh!
Here is the full code attached.

Temperature.ino (11.2 KB)

That is looking very good. Very compact, effective coding. Nicely done.

Glad to be of assistance,

Rob

The Ambient F007TH Sensor appears to be the same as the (Australia & NZ) Jaycar XC-0328 kit and the Jaycar XC0329 individual sensor. I just noticed today that they have put both of these on clearance, so this connection is only likely to be of use to those who already have one.

I have been trying to understand the basic parts of the code. I would like to use a NodeMCU ESP8266 or WEMOS equivalent to replace the CC3000 in the existing code.

If I understand correctly, one of the key lines is:

pinMode(RxPin, INPUT);

I can see that "int RxPin = 8; //The number of signal from the Rx"

I don't understand what this corresponds to. Is it the number of potential sensors? Is it the input on the CC3000?

Using a RXB6 receiver module I was able to decode 433MHz codes from a 433MHz RF switch.
The code used for that used
"mySwitch.enableReceive(13); // Receiver on interrupt GPio 13 => that is pin D7"

Would the line become?:
pinMode.enableReceive(13);

Any assistance would be very much appreciated.

pinMode(RxPin, INPUT);

I can see that "int RxPin = 8; //The number of signal from the Rx"

I don't understand what this corresponds to.

Arduino pin 8 is used in this case as an input to read the data output by the receiver. Any cheap 433 MHz receiver should work with the code in reply #33 above.

int RxPin = 8;

means that instead of using the character/number "8" to represent the number of the pin in question, the label "RxPin" can be used instead. Change 8 to another number in that line and that number will be used by the rest of the program wherever RxPin is used. The comment added after the // is quite unhelpful. As jremington suggests the 433MhzRx's output is attached to pin 8 which is the input in this case.

Using a RXB6 receiver module I was able to decode 433MHz codes from a 433MHz RF switch.
The code used for that used
"mySwitch.enableReceive(13); // Receiver on interrupt GPio 13 => that is pin D7"

Would the line become?:
pinMode.enableReceive(13);

This is more confusing to me. mySwitch.enableReceive(13); would be some sort of procedure call either in another part of the same program or a library call. If it is an Arduino it sounds some what unusual as I am not aware that 13 is the interrupt pin on an Arduino. Usually people just make use of Pin13 as an output with a status LED on it.

pinMode() sets the operation of a given pin as either an input or as an output, and should not be considered interchangeable with mySwitch (most likely a library call?).

If you have code working with CC3000 it is unlikely you can swap a NodeMCU ESP8266 or WEMOS in and not adjust your code to the new hardware. Most likely you will need appropriate libraries for the new hard ware and then have to adapt the main program to use the new hardware library.

I hope this helps, R

Thank you both for such helpful and prompt responses.

Looks like I will need to do more research on this topic, but at least I appear to have found working code and a well known name and model number of these sensors.

I wonder if Ambient is going to discontinue these sensors or it is just a decision taken by the local importer/distributor Jaycar?

I had to swap from a "Bios" weather station setup using a USB interface, to my current one with Oregon Scientific + Arduino->USB and it works so much better. I bought a second OS Anemometer as a backup, as that was what broke on the Bios (I had bought 2 Bios systems when they were no longer sold, so third time unlucky). However the swap to the OS+Arduino solution is so much better, forced me to move on. I also have a 3-D printer now so could probably print repairs eg broken cups. :slight_smile:

Good luck...