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: Help me decode this 434mhz signal...? - #20 by Riva - Project Guidance - Arduino Forum ).
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
* (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();
}
}