Hi,
I looked around for details on these and there were some good threads (e.g. 433 MHz RF - Temperature and humidity sensor - #67 by Dzeivi ) but no-one had published how to read the cheap no-name sensors off ebay like this one.
I managed to receive the signal adding a 'custom' protocol to the standard arduino rc-switch library, and then decode the 36-bit response to give temperatre, humidity, channel #, battery % and pairing code.
In case anyone else has this sensor and would like to integrate it into their arduino project, I would attach the required information in a spreadsheet, but it doesn't seem to allow me to do so so here is a bit pattern.... so
Custom protocol for rc-switch library (tested on 3 different receiver types)
{ 570, { 1, 16 }, { 1, 3 }, { 1, 7 }, false} (add this line to protocol defintions around line 80 of RCSwitch.cpp in the arduino rc-switch library)
Code snippet to decode and output the data on an Arduino uno:
static const char* bin2tristate(const char* bin);
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength);
void deocodedoutput(unsigned long rxValue, char* climate, int channel, int temperature, int humidity, int battery)
{
Serial.print("Result "); Serial.print(rxValue); Serial.print(" in binary "); Serial.println(climate);
Serial.print("Ch"); Serial.print(channel); Serial.print(": "); Serial.print((float) temperature/10); Serial.print("C, ");
Serial.print(humidity); Serial.print("% R.H., battery ");Serial.print(25*battery); Serial.print("% and pairing code ");
// truncate climate for pairing code
*(climate+12) = '\0'; Serial.println((climate+4));
}
void decodeClimate(unsigned long rxValue) {
char* climate = dec2binWzerofill(rxValue, 36); // 36 characters of data received - if not don't call routine to try to decode it...
// climate will be a char* like: 000000001001101000001011101000110110 which means: 18.6degC, 54% rel humidity
int humidity = 0, temperature = 0, channel = 0, battery = 0;
// for further study - possibly do check before coming to this routine....
// check valid result - check digit at position 28 should be a zero
// digits 4 to 11 should be the (known) pairing code
if ((*(climate + 28) != '0') || (!equivalent((climate + 4), (climate + 4), 8)))
{
Serial.println("Rx error!");
return;
}
// humidity is last 7 characters (i<7 assumes 7 here i.e. digits 0 to 6 inclusive...)
for (int i = 0; i<7; i++)
{
humidity = 2*humidity + ((*(climate + 29 + i) == '1') ? 1 : 0);
}
// temperature in units of 0.1degC is 11 characters starting in position 17 to position 29
// i.e a temperature of 18.6degC will be indicated by an int of 186 here...
int one = 1, zero = 0;
// invert bits if negative temperature... indicated by bit 16 being '1'
if (*(climate + 16) == '1')
{
one = 0;
zero = 1;
}
for (int i = 0; i<11; i++)
{
temperature = 2*temperature + ((*(climate + 17 + i) == '1') ? one : zero);
}
// if negative, need to add 1
if (*(climate + 16) == '1')
{
temperature = -(temperature + 1);
}
// Known: channel on instrument is bits 15/16 - value 0, 1, 2 for channel 1, 2, 3
// Guess??: 2 digits before channel number are battery% say 25%, 50%, 75%, 100%....
for (int i = 0; i<2; i++)
{
channel = 2*channel + ((*(climate + 14 + i) == '1') ? 1 : 0);
battery = 2*battery + ((*(climate + 12 + i) == '1') ? 1 : 0);
}
channel++; battery++;
// print decoded output
deocodedoutput(rxValue, climate, channel, temperature, humidity, battery);
}
// check 'numchars' characters of a character string and return '1' if equivalent and '0' if not
boolean equivalent(char* data, char* pairingcode, int numchars)
{
for (int i=0; i<numchars; i++)
{
if (*(data+i) != *(pairingcode+i))
{
return(0);
}
}
return(1);
}
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
static char bin[64];
unsigned int i=0;
while (Dec > 0) {
bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0';
Dec = Dec >> 1;
}
for (unsigned int j = 0; j< bitLength; j++) {
if (j >= bitLength - i) {
bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
} else {
bin[j] = '0';
}
}
bin[bitLength] = '\0';
return bin;
}
Regards