Pages: [1]   Go Down
Author Topic: Reading RF packets  (Read 1658 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
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: http://arduino.cc/forum/index.php/topic,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: http://arduino.cc/forum/index.php/topic,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!!!


Code:
/*
 * 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
 * (http://www.practicalarduino.com/projects/weather-station-receiver).
 * For more info:
 * http://kayno.net/2010/01/15/arduino-weather-station-receiver-shield/
 *
 *
 */

#define INPUT_CAPTURE_IS_RISING_EDGE()    ((TCCR1B & _BV(ICES1)) != 0)
#define INPUT_CAPTURE_IS_FALLING_EDGE()   ((TCCR1B & _BV(ICES1)) == 0)
#define SET_INPUT_CAPTURE_RISING_EDGE()   (TCCR1B |=  _BV(ICES1))
#define SET_INPUT_CAPTURE_FALLING_EDGE()  (TCCR1B &= ~_BV(ICES1))

#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
#define WEATHER_PACKET_BIT_LENGTH   19

// pulse widths. short pulses ~500us, long pulses ~1000us. 50us tolerance
#define SHORT_PULSE_MIN_WIDTH       420/TIMER_PERIOD_US
#define SHORT_PULSE_MAX_WIDTH       570/TIMER_PERIOD_US
#define LONG_PULSE_MIN_WIDTH        1420/TIMER_PERIOD_US
#define LONG_PULSE_MAX_WIDTH        1570/TIMER_PERIOD_US
#define BIG_PULSE_MIN_WIDTH        2920/TIMER_PERIOD_US
#define BIG_PULSE_MAX_WIDTH        3070/TIMER_PERIOD_US

// 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 */
ISR(TIMER1_CAPT_vect){

  // 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
  if(INPUT_CAPTURE_IS_RISING_EDGE()) {
    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) {
        long_count++;
      }
      else if(((captured_period >= SHORT_PULSE_MIN_WIDTH) && (captured_period <= SHORT_PULSE_MAX_WIDTH)) && packet_start) {
        short_count++;
      }
      else {
        // not a long or short pulse, therefore not a valid bitstream
        WEATHER_RESET();
      }
    }
    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;
      packet_bit_pointer++;
    }
    else if(((captured_period >= LONG_PULSE_MIN_WIDTH) && (captured_period <= LONG_PULSE_MAX_WIDTH))) {
      weather_packet[packet_bit_pointer] =  1;
      packet_bit_pointer++;
    }


  }

  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() {
  Serial.begin(115200);

  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) );
  SET_INPUT_CAPTURE_RISING_EDGE();
  //Timer1 Input Capture Interrupt Enable, Overflow Interrupt Enable  
  TIMSK1 = ( _BV(ICIE1) | _BV(TOIE1) );

  //  attachInterrupt(0, rise, RISING);
  WEATHER_RESET();

  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
    Serial.println();

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

    Serial.println();
    //#endif
    packet_start = true;
    WEATHER_RESET();

  }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 613
Posts: 49310
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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?
Logged

Pages: [1]   Go Up
Jump to: