Pages: [1]   Go Down
Author Topic: Reading RF packets  (Read 1671 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A while ago with the help of the forum I decoded the packets for my 434mhz weather station.  If you check out our discussion on the earlier thread where you can see the bit stream and our decoding (this thread:,110662.15.html) you'll see that the stream is not manchester encoded, so I am just using simple code to try to read the bits into an array to get the same values that we saw when using Audacity.  I started by counting the "big" pulse as the packet start, long pulses as 1, short pulses as 0.  I begin reading packet data after the first 7 bits (1010101) have been received, which would leave 19 more bits in the stream to read and then decode (see Riva's post here:,110662.msg840578.html#msg840578 ).

Here is my simple code so far based off of another sketch (which was for a Manchester encoded weather station, thus the modifications/simplifications).  I'm not sure why I am not seeing all of the correct bits come through my code that I identify when looking at a bit capture with Audacity.  Can anyone point me in the right direction? 

Thank you!!!

 * Modified from "Thermor" DG950R Weather Station receiver v 0.3
 * Receives data from a Weather Station receiver, via
 * a 433Mhz RF receiver connected to pin 8 of the arduino, and outputs
 * to serial.
 * Based on the Practical Arduino Weather Station Receiver project
 * (
 * For more info:

#define INPUT_CAPTURE_IS_RISING_EDGE()    ((TCCR1B & _BV(ICES1)) != 0)

#define WEATHER_RX_LED_ON()         ((PORTD &= ~(1<<PORTD6)))
#define WEATHER_RX_LED_OFF()        ((PORTD |=  (1<<PORTD6)))

#define WEATHER_RESET()             { short_count = packet_bit_pointer = long_count = 0; weather_rx_state = RX_STATE_IDLE; current_bit = BIT_ZERO; WEATHER_RX_LED_OFF(); packet_start = false; }

#define TIMER_PERIOD_US             4

// pulse widths. short pulses ~500us, long pulses ~1000us. 50us tolerance

// number of shorts in a row before the stream is treated as valid
#define SHORT_COUNT_SYNC_MIN        3
#define LONG_COUNT_SYNC_MIN         4

// states the receiver can be
#define RX_STATE_IDLE               0 // waiting for incoming stream
#define RX_STATE_RECEIVING          1 // receiving valid stream
#define RX_STATE_PACKET_RECEIVED    2 // valid stream received

#define BIT_ZERO                    0
#define BIT_ONE                     1

//byte locations of generic weather data in weather_packet[] array
#define WEATHER_STATION_ID          0
#define WEATHER_PACKET_TYPE         1

//types of packets
#define PACKET_TYPE_HUM             0
#define PACKET_TYPE_TEMP            1

#define DEBUG

// Type aliases for brevity in the actual code
typedef unsigned int       uint; //16bit
typedef signed int         sint; //16bit

uint captured_time;
uint previous_captured_time;
uint captured_period;
uint current_bit;
uint last_bit;
uint packet_bit_pointer;
uint short_count;
uint long_count;
uint weather_rx_state;

volatile bool packet_start = false;
volatile bool packet_end = false;
volatile bool ignore = false;

// byte arrays used to store incoming weather data
byte weather_packet[(WEATHER_PACKET_BIT_LENGTH)];
byte last_weather_packet[(WEATHER_PACKET_BIT_LENGTH)];

// packet counter - 4 identical packets in a row means the packet is valid
int packet_count = 0;

/* Overflow interrupt vector */
ISR(TIMER1_OVF_vect){                 // here if no input pulse detected

/* ICR interrupt vector */

  // Immediately grab the current capture time in case it triggers again and
  // overwrites ICR1 with an unexpected new value
  captured_time = ICR1;

  //immediately grab the current capture polarity and reverse it to catch all the subsequent high and low periods coming in
    SET_INPUT_CAPTURE_FALLING_EDGE();      //previous period was low and just transitioned high  
  else {
    SET_INPUT_CAPTURE_RISING_EDGE();       //previous period was high and transitioned low    

  // calculate the current period just measured, to accompany the polarity now stored
  captured_period = (captured_time - previous_captured_time);

  // Analyse the incoming data stream. If idle, we need to detect the start of an incoming weather packet.
  // Incoming packet starts with a big pulse and the sequence 101010.
  if(weather_rx_state == RX_STATE_IDLE) {
    if( ((captured_period >= BIG_PULSE_MIN_WIDTH) && (captured_period <= BIG_PULSE_MAX_WIDTH))) {
      // received a big pulse - indicating the start of a packet
      packet_start = true;

    else {

      if(((captured_period >= LONG_PULSE_MIN_WIDTH) && (captured_period <= LONG_PULSE_MAX_WIDTH)) && packet_start) {
      else if(((captured_period >= SHORT_PULSE_MIN_WIDTH) && (captured_period <= SHORT_PULSE_MAX_WIDTH)) && packet_start) {
      else {
        // not a long or short pulse, therefore not a valid bitstream
    if((short_count >= SHORT_COUNT_SYNC_MIN) && (long_count >= LONG_COUNT_SYNC_MIN)) {
      weather_rx_state = RX_STATE_RECEIVING;
  else if(weather_rx_state == RX_STATE_RECEIVING) {
    if(((captured_period >= SHORT_PULSE_MIN_WIDTH) && (captured_period <= SHORT_PULSE_MAX_WIDTH))) {  
      weather_packet[packet_bit_pointer] =  0;
    else if(((captured_period >= LONG_PULSE_MIN_WIDTH) && (captured_period <= LONG_PULSE_MAX_WIDTH))) {
      weather_packet[packet_bit_pointer] =  1;


  if(packet_bit_pointer > WEATHER_PACKET_BIT_LENGTH) {
    // full packet received, switch state to RX_STATE_PACKET_RECEIVED
    weather_rx_state = RX_STATE_PACKET_RECEIVED;

  // save the current capture data as previous so it can be used for period calculation again next time around
  previous_captured_time = captured_time;      


void setup() {

  DDRB = 0x2F;   // B00101111
  DDRB  &= ~(1<<DDB0);    // PBO(ICP1) input
  PORTB &= ~(1<<PORTB0);  // ensure pullup resistor is also disabled
  DDRD  |=  B11000000;    // (1<<PORTD6);   //DDRD  |=  (1<<PORTD7); (example of B prefix)

  //ICNC1: Input Capture Noise Canceler         On, 4 successive equal ICP1 samples required for trigger (4*4uS = 16uS delayed)
  //ICES1: Input Capture Edge Select            1 = rising edge to begin with, input capture will change as required
  //CS12,CS11,CS10   TCNT1 Prescaler set to 0,1,1 see table and notes above
  TCCR1A = B00000000;   //Normal mode of operation, TOP = 0xFFFF, TOV1 Flag Set on MAX
  //This is supposed to come out of reset as 0x00, but something changed it, I had to zero it again here to make the TOP truly 0xFFFF
  TCCR1B = ( _BV(ICNC1) | _BV(CS11) | _BV(CS10) );
  //Timer1 Input Capture Interrupt Enable, Overflow Interrupt Enable  
  TIMSK1 = ( _BV(ICIE1) | _BV(TOIE1) );

  //  attachInterrupt(0, rise, RISING);

  Serial.println("\"joshhawk\" Weather Station receiver v0.01");
  Serial.println("Ready to receive weather data");

 * main loop

void loop() {

  // weather packet ready to decode
  if(weather_rx_state == RX_STATE_PACKET_RECEIVED) {

    //#ifdef DEBUG

    for(int i = 0; i < ((WEATHER_PACKET_BIT_LENGTH)); i++) {
      Serial.print(" ");

    packet_start = true;


Seattle, WA USA
Offline Offline
Brattain Member
Karma: 644
Posts: 50452
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not sure why I am not seeing all of the correct bits come through my code that I identify when looking at a bit capture with Audacity.
Isn't Audacity operating on audio input?

Pages: [1]   Go Up
Jump to: