Go Down

Topic: Reading RF packets (Read 1 time) previous topic - next topic

joshhawk

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: [Select]

/*
* 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();

 }
}

PaulS

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?

Go Up