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

If you are interested to decode the signal from this sensor by yourself, I have described an example of how to do it. More advanced example can be found here too.

Hi,

Thanks for that information, I think those sensors have a different protocol though and I've just noticed that the image of the bit pattern of the sensor I had did not come through in the first post. So here it is again.

regards

IMHO rc-switch can handle up to 32 bit packets. In your case the packet is 36 bit long. There must be more changes to the rc-switch library than just add your custom protocol definition.

The function mySwitch.getReceivedBitlength() in the rc-switch library returned the result 36 bits long, but the first 4 bits are always zero and not significant. So only 32 bits are actually used. I've no idea why it works if it shouldn't but perhaps that is the explanation?

There is a 64-bit version for rc-switch, if you really care. Only a few modifications is required to the code. But if you are happy with your device , it is fine.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.