Ebay 433MHz Temperature and Humidity Sensor

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