Choosing a good 433mhz receiver

Getting ready to start working with 433mhz sensors.
I just ordered probably the cheapest Chinese 433mhz receivers available from Amazon. Made by WayInTop, with what looks like an adjustable cap in middle of board. This will do for a short time, but I'm interested in a bit better receiver. Could one or more of ya recommend a couple of better receivers and associated libraries for the Arduino please.

Thanks Al

The superheterodyne receivers are more sensitive, and much more selective.


Do you know if this receiver can be used to decode/receive Acurite signals?


Yes, at least for some Acurite sensors, if the signals are transmitted on the 434 MHz band.

Ok, I received the new superhet today and got it all hooked up.
The noise seems to be just as bad as that $1 receiver, plus the arduino is not decoding anything.
The cheep Rx at least occasionally would detect sync.
So ... now I gotta decide if in fact I got a good receiver, and if so start digging in and see if I can get it going. Else order another Rx. Thoughts comments?

Oh yea, what's you recommended library for this receiver.


Of course it is. When not locked onto a suitable signal, those modules all generate white noise.

Suspect the rest of your setup, and verify all other parts of the operation, before you blame the new part.

I also recommend a superheterodyne type of receiver, even it may be more expensive. The only problem I encountered that some 433MHz keyfobs may issue signals that slightly deviate from 433,92MHz and suppressed by the narrow band window of such receivers. But that's being rather a keyfob's problem, not receiver's. You can have a look at some of my projects where such superheterodyne modules are used.

Just to verify and make sure, the RXB6 is a superhet, correct?


Please post a link to what you are calling the RXB6.

If I found the right one the document states: "receiver structure is super hetero-dyne received signal is OOK ,After
received signal it will output COMS signal to external decoder IC for
decoding .".
So, unless your FOB uses OOK, on-off-keying, you will need to research further.


The receiver shown in reply #11 is a crystal controlled superhet.

plus the arduino is not decoding anything

That is almost certainly not the fault of the receiver. There are countless encoding schemes and until you know the details, you probably won't get far.

This tutorial describes an excellent approach to analyzing typical 433 MHz transmit protocols: Reverse Engineer Wireless Temperature / Humidity / Rain Sensors — Part 1 « RAYSHOBBY.NET

Yea, I read that article. It's a good one. What I need to do now is read it again and study it a bit better.

I was hoping for some, partial turnkey solution for Acurite that partially works. I'm usually real good at reverse engineering this stuff, but I'm now 70 and my bulldog tenacity is slowly dwindling.
Still enjoy this crap though!


The manufacturers keep changing the protocol details, but there are several Acurite decoders on line that will get you started. Surely you have found the WXshield website.

Some time ago I decoded the transmission of an ACURITE W091 Temperature Sensor. My notes indicate the following:

9 milliseconds start bit, 4 milliseconds RF off = 1 bit, 2 milliseconds RF off = 0 bit.

Transmissions: 9 ms start bit, followed by 24 bits repeated 11 times. Each 24 bit packet consists of 10 bit sensor ID, 12 bits temperature in degrees C*10, then two bits of unknown function. Negative temperature is stored as 2's complement. The sensor ID is a rolling code and changes every time you disconnect and reconnect the battery.

Yep I got WxShield's white paper downloaded. I also have a nice storage scope to capture this stuff. However, with constant noise triggering is a challenge.

Do you still have the code you did for the W091? Can you share?


That is a fact of life. When the receiver locks on to a signal, then in the absence of external interference, the pulses obey certain timing rules. Your program has to know those rules, and apply them to determine whether a signal is valid. If you spend some time looking at other people's code, it should become clear how it works.

I did not write any code for the W091, I just used Audacity to visualize the signal, and verify the encoding.

Here is some example receiver code for a similar sensor:

// update 1/8/2019 tank monitor, working 
// receives and decodes LaCrosse TX6U temp sensor (433 MHz)
// YXR15 has RF ON = active high O/P (see definition of RF_ON/OFF below
// superregenerative receivers have mostly active low O/P
// SJR initially written 11/2017
// this version prints only one of 1st and 2nd copy of message

#define RF_IN   (1<<PD2)   //RF data in PORTD, PD2, ACTIVE HIGH receiver (Arduino digital pin 2)
#define LED      (1<<PB5)  // digital pin 13

// The following defines are for a receiver with RF ON = active low output
// switch them if RF ON = active high
// also, definitions must be consistent with definition for RF_IN port bit

#define RF_OFF  0
#define RF_ON (1<<PD2)

#define BUFSZ 10
char buf[BUFSZ + 1]; //packet character buffer

// parity table  0 1 2 3 4 5 6 7 8 9
char   ptable[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2}; //# bits set in BCD nibble

unsigned char Bit, BitCnt, ErrCnt, ErrCode, BufPtr;
unsigned char c, idx;
unsigned char BitTime, sensor_id;
signed int tempc, tempf;
int p; //parity bit for data digits

unsigned long LastMsgPrint = 10000UL; //satisfies test in loop()

void setup() {
  Serial.println("TX6U-rx 01/08/2019");

// set up Timer2 for 8 usec ticks

  TCCR2A = 0; //normal counter mode
  TCCR2B = (1 << CS22) | (1 << CS20);    //Timer2 prescaler = CPU clock/128 = 8 usec ticks

void loop() {

  PORTB &= ~LED; //LED off
  ErrCode = 0;

  //  loop: wait for possible transmissions.
  while (1)
    while ((PIND & RF_IN) == RF_OFF);     //wait for RF on

    TCNT2 = 0;                         //zero 8 usec counter
    while ((PIND & RF_IN) == RF_ON);    //wait for RF off, time the on pulse

    if (TCNT2 > 162) break;             //got long RF pulse (expect ~ 172 ticks)

        if (TCNT2 > 182) bail_out();      //probably not LaCrosse protocol

  ErrCnt = 0;

  //  possible start of packet, RF is OFF. Check for rest of preamble (3 more zero bits)

  for (idx = 0; idx < 3; idx++)

    TCNT2 = 0;
    while ((PIND & RF_IN) == RF_OFF);  //time RF off period, expect 1 ms = 125 ticks
    BitTime = TCNT2;

    if ((BitTime < 115) || (BitTime > 135)) ErrCnt++;

    TCNT2 = 0;
    while ( (PIND & RF_IN) == RF_ON);  //time the RF on period, expect ~1.5 ms ~ 172 ticks
    BitTime = TCNT2;

    if ((BitTime < 162) || (BitTime > 182)) ErrCnt++;


  if (ErrCnt > 0) ErrCode |= 1; //glitchy preamble, or not LaCrosse protocol

  // attempt to read and decode packet

  BitCnt = 0;
  BufPtr = 0;
  c = 0;
  while (BitCnt < 40)               //0 to 39
    PORTB |= LED;               //led on

    while ((PIND & RF_IN) == RF_OFF);  //wait for on, expect 1 ms = 125 ticks

    TCNT2 = 0;                      //time the RF pulse
    while ((PIND & RF_IN) == RF_ON);  //wait for off, expect 0.6 ms = 0 or 1.5 ms = 1
    BitTime = TCNT2;

    Bit = 0;
    if (BitTime < 125) Bit = 1;      // ~ bisect 0/1 timing (measured 72/172 ticks)

    c = (c << 1) | Bit;           //get bit, LSB first


    if (BitCnt % 4 == 0) //remainder modulo 4
      buf[BufPtr++] = c; //got 4 bits, store nibble in buf[]
      c = 0;

  }   //end while BitCnt

  BufPtr--;            //point to last character in buffer

  //   check message integrity
  //  Lacrosse TX6U, TX3, version 1: 10 nibbles

  if (buf[0] != 10) ErrCode |= 2;      //message length not ten nibbles
  if (buf[1] !=  0) ErrCode |= 2;      //not a temperature sensor (humidity?)

  //  checksum

  c = 0;
  for (idx = 0; idx < BufPtr; idx++) c += buf[idx]; // add chars in first 9 positions

  if ( (c & 0x0F) != buf[BufPtr]) ErrCode |= 4 ;   //checksum doesn't match

  // check that first two digits of temperature are repeated

  if ( (buf[4] != buf[7]) || (buf[5] != buf[8]) ) ErrCode |= 8; // don't repeat

  p = ptable[buf[4]] + ptable[buf[5]] + ptable[buf[6]]; //calculate data parity
  if ( (p & 1) != (buf[3] & 1) ) ErrCode |= 16; //parity error

  // done decoding RF

  if ( (ErrCode & 0x1E) == 0 ) // OK except for possibly forgivable glitches in preamble


    PINB &= ~LED;   //LED off
    sensor_id = ((buf[2] << 4) | buf[3]) >> 1;

    tempc = 100 * ((int) buf[4]) + 10 * ((int) buf[5]) + (int) buf[6]; //celcius*10
    tempc = tempc - 500;              //subtract offset applied by sensor
    tempf = (tempc * 90 + 25) / 50 + 320; //deg F*10 rounded up for positive temperatures

    //   convert entire message to hex for display

    for ( idx = 0; idx <= BufPtr; idx++)
      c = buf[idx];
      if (c < 10) c += '0';   else c += 'a' - 10;
      buf[idx] = c;
    } //end for idx
    buf[BufPtr + 1] = 0;       //end the string
    if (millis() - LastMsgPrint > 2000UL) { //skip second copy if first was printed
      LastMsgPrint = millis(); //save the time!
      Serial.println(tempc);  //deg C*10
  } //end if ErrCode

} //end loop()

Hmmmm ... Audacity huh? I've seen that mention A LOT on this adventure. I take it it's free, and do I need a SDR to go with it? Fill me in please.


Audacity is used in the RaysHobby tutorial, linked in reply #12.

It would be a good idea to reread that article.

The transmitter (not the receiver) should trigger the scope.

I know you can't use the receiver. But you have a good idea. I'll get the Xmitr off the porch and do a little exploring for the xmit send pin.