Arduino code to receive data from an Oregon Scientific weather station

 

NO TESTED

 

// 2012-09-06 - Oregon V2 decoder modified - Olivier Lebrun <olivier.lebrun@connectingstuff.net>
// 2012-06-21 - Oregon V2 decoder added - Dominique Pierre (zzdomi)
// 2012-06-21 - Oregon V3 decoder revisited - Dominique Pierre (zzdomi)
// New code to decode OOK signals from weather sensors, etc.
// 2010-04-11 Jean-Claude Wippler <jcw@equi4.com>

//Todo merge back from https://github.com/jcw/jeelib/tree/master/examples/RF12/ookRelay2

//http://playground.arduino.cc/Code/HomeEasy

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
int incomingByte = 0; // for incoming serial data


#include "DecodeOOK.h"
#include "CrestaDecoder.h"
#include "HezDecoder.h"
#include "KakuDecoder.h"
#include "OregonDecoderV1.h"
#include "OregonDecoderV2.h"
#include "OregonDecoderV3.h"
#include "XrfDecoder.h"
#include "EMxDecoder.h"
#include "FSxDecoder.h"
#include "KSxDecoder.h"
#include "VisonicDecoder.h"

//433
OregonDecoderV1 orscV1;
OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;
CrestaDecoder cres;
KakuDecoder kaku;
XrfDecoder xrf;
HezDecoder hez;
//868
VisonicDecoder viso;
EMxDecoder emx;
KSxDecoder ksx;
FSxDecoder fsx;

#define PORT 2

volatile word pulse;

#if defined(__AVR_ATmega1280__)//Arduino
void ext_int_1(void) {
#else//JeeNode
ISR(ANALOG_COMP_vect) {
#endif
 static word last;
 // determine the pulse length in microseconds, for either polarity
 pulse = micros() - last;
 last += pulse;
}

void reportSerial (const char* s, class DecodeOOK& decoder) {
 byte pos;
 const byte* data = decoder.getData(pos);
 Serial.print(s);
 Serial.print(' ');
 for (byte i = 0; i < pos; ++i) {
 //Serial.print(data[i] >> 4, HEX);
 //Serial.print(data[i] & 0x0F, HEX);
 Serial.print(data[i] >> 4, DEC);
 Serial.print(data[i] & 0x0F, DEC);
 
 }
 
 // Serial.print(' ');
 // Serial.print(millis() / 1000);
 Serial.println();
 
 decoder.resetDecoder();
}


void setup () {
 Serial.begin(115200);
 Serial.println("\n[ookDecoder]");

#if !defined(__AVR_ATmega1280__)//JeeNode code
 pinMode(13 + PORT, INPUT); // use the AIO pin
 digitalWrite(13 + PORT, 1); // enable pull-up

// use analog comparator to switch at 1.1V bandgap transition
 ACSR = _BV(ACBG) | _BV(ACI) | _BV(ACIE);

// set ADC mux to the proper port
 ADCSRA &= ~ bit(ADEN);
 ADCSRB |= bit(ACME);
 ADMUX = PORT - 1;
#else//Arduino
//attach our interrupt handler on port int1 (arduino uno port2)
 attachInterrupt(1, ext_int_1, CHANGE);
//no idea what this is for...
 DDRE &= ~_BV(PE5);
 PORTE &= ~_BV(PE5);
#endif

mySwitch.enableTransmit(10); // Using Pin #10
}

void loop () {
 static int i = 0;
 cli();
 word p = pulse;
 
 pulse = 0;
 sei();

//if (p != 0){ Serial.print(++i); Serial.print('\n');}

//433Mhz
 if (p != 0) {
 Serial.print("[pulse]");
 Serial.print(p, HEX);
 Serial.println();
 if (orscV1.nextPulse(p))
 reportSerial("OSV1", orscV1);
 if (orscV2.nextPulse(p))
 reportSerial("OSV2", orscV2); 
 if (orscV3.nextPulse(p))
 reportSerial("OSV3", orscV3); 
 if (cres.nextPulse(p))
 reportSerial("CRES", cres); 
 if (kaku.nextPulse(p))
 reportSerial("KAKU", kaku); 
 if (xrf.nextPulse(p))
 reportSerial("XRF", xrf); 
 if (hez.nextPulse(p))
 reportSerial("HEZ", hez); 
 }

//868Mhz
 if (p != 0) {
 if (viso.nextPulse(p))
 reportSerial("VISO", viso);
 if (emx.nextPulse(p))
 reportSerial("EMX", emx);
 if (ksx.nextPulse(p))
 reportSerial("KSX", ksx);
 if (fsx.nextPulse(p))
 reportSerial("FSX", fsx);
 }
 if (Serial.available() > 0) {
 // read the incoming byte:
 incomingByte = Serial.read();
 mySwitch.send(5393, 24);
 }
}

 

 

 

Result from other sensor:

[ookDecoder]
[pulse]D0
[pulse]E8
[pulse]198
[pulse]20
[pulse]26C
[pulse]14
[pulse]53C
[pulse]2C
[pulse]8
[pulse]14
[pulse]8
[pulse]F0
[pulse]1E4
[pulse]70
[pulse]13B8
[pulse]6C
[pulse]464
[pulse]90
[pulse]254
[pulse]94
[pulse]88
[pulse]28
[pulse]D4
[pulse]104
[pulse]100
[pulse]144
[pulse]8C
[pulse]3C
[pulse]10
[pulse]38
[pulse]1750
[pulse]74
[pulse]2E8
[pulse]C0
[pulse]7C
[pulse]12C
[pulse]30 

...

..

..

 

Wireless Weather Station Outdoor Sensor Receiving Packets With the Arduino

NOT TESTED

#include <Arduino.h>

#define DEBUG

#define ICP1_PIN 8
#define POWER_PIN 10

//buffer size
#define MAX_RECEIVES 128
//microseconds for one timer tick (4us for 64 prescaler and F_CPU=16MHz)
#define TIMER_PULSE_MICROSECONDS 4
//weather station channel
#define SELECTED_CHANNEL 3
//pulse intervals
#define START_SEQUENCE_MIN 3500 
#define START_SEQUENCE_MAX 4000
#define PULSE_MIN 350
#define PULSE_MAX 450
#define SPACE_ONE_MIN 1600
#define SPACE_ONE_MAX 2000
#define SPACE_ZERO_MIN 800
#define SPACE_ZERO_MAX 1000
//UART baud rate
#define UART_SPEED 115200
//number of received pin level changes
volatile int receives = 0;
//buffers for pin levels
volatile uint32_t receive_times[MAX_RECEIVES];
volatile bool levels[MAX_RECEIVES];
//buffer for decoded data (theoretical maximum is half of pin changes)
bool decodedData[MAX_RECEIVES/2];
//current watched edge flag 
bool risingEdge = false;
//time to try decoding flag
volatile bool stop_receive = false;
//result of decoded data
float outdoorTemp = 0.0;


void setup() {
 //optional pin for power RF receives
 pinMode(POWER_PIN, OUTPUT);
 digitalWrite(POWER_PIN,HIGH);
 //input capture T1 pin
 pinMode(ICP1_PIN, INPUT);
 //T1 initialization
 initTimer1();

Serial.begin(UART_SPEED);
 
#ifdef DEBUG 
 Serial.println("Ready");
#endif 
}

void loop() {
 //decode request
 if(stop_receive)
 { 
 decodeData(); 
 stop_receive = false; 
 } 
}

ISR(TIMER1_COMPA_vect) {
 //no pin change captured long time -> buffer not empty -> try decode received data
 if(receives>0)
 stop_receive = true;
}

ISR(TIMER1_CAPT_vect) {
 //reset time
 TCNT1H = 0;
 TCNT1L = 0; 
 //read timestamp
 byte low = ICR1L; 
 byte high = ICR1H;
 //calc gap between level changes (microseconds)
 uint32_t gap = TIMER_PULSE_MICROSECONDS * (((uint32_t)high << 8) | (uint32_t)low);
 //write current level change 
 intRecv(gap);

//change edge detection for next capture
 if (risingEdge) 
 TCCR1B &= ~(1<<ICES1);
 else 
 TCCR1B |= (1<<ICES1);

risingEdge = !risingEdge; 
}

//----------------------------------------- T1 initilalization ---------------------------------------------
void initTimer1() { 
 TCCR1A = 0;
 TCCR1B = 3; //64 prescaler
 TCCR1C = 0;

//OC = 30ms
 OCR1AH = 0x1D;
 OCR1AL = 0x4C;

TIMSK1 = (1<<ICIE1) | (1<<OCIE1A);
}

//----------------------------------------- start measuring ---------------------------------------------
void startMeasure()
{
 digitalWrite(POWER_PIN,HIGH);
 TCCR1B = 3; 
}

//----------------------------------------- stop measuring ---------------------------------------------
void stopMeasure()
{
 digitalWrite(POWER_PIN,LOW);
 TCCR1B = 0; 
}

//----------------------------------------- write current level change ---------------------------------------------
void intRecv(uint32_t gap)
{
 if(stop_receive)
 return;
 
 if(receives < MAX_RECEIVES)
 {
 if(receives == 1)
 {
 if(gap > START_SEQUENCE_MIN and gap < START_SEQUENCE_MAX)
 {
 levels[1] = risingEdge;
 receive_times[1] = gap;
 
 receives++; 
 }
 else
 {
 levels[0] = risingEdge;
 receive_times[0] = 0; 
 }
 }
 else if(gap > PULSE_MIN)
 {
 levels[receives] = risingEdge;
 receive_times[receives] = gap;

receives++; 
 }
 else if(receives > 1)
 {
 stop_receive = true;
 }
 else
 {
 levels[0] = risingEdge;
 receive_times[0] = 0; 
 receives = 0;
 }
 }
 else
 stop_receive = true;
}

//----------------------------------------- decode data stored in receive buffers ---------------------------------------------
void decodeData()
{
 noInterrupts();

#ifdef DEBUG 
 uint32_t duration = 0;
 
 for(int i=0;i<receives;i++)
 {
 duration += receive_times[i];
 }

Serial.print(F("Changed "));Serial.print(receives,DEC);
 Serial.print(F(" times. Duration "));Serial.print(duration, DEC);
 Serial.println(" us");
 
 for(int i=0;i<receives;i++)
 {
 if(i>0)
 {
 Serial.print(receive_times[i], DEC);
 Serial.print("");
 }
 
 if(levels[i])
 Serial.print("/");
 else
 Serial.print("\\"); 
 }

Serial.println("");
 
#endif

int len = 0;
 bool decodingOk = false;

for(int i=0;i<receives;i++)
 {
 if(i>0)
 {
 unsigned long gap = receive_times[i];

//start sequence
 if((levels[i-1] == 0) && (gap > START_SEQUENCE_MIN) && (gap < START_SEQUENCE_MAX))
 {
 if(len > 0)
 {
 analyzeDecodedData(len);
 }
 
#ifdef DEBUG 
 Serial.println(F("New data:")); 
#endif
 len = 0;
 decodingOk = true;
 }
 //pulse active
 else if(decodingOk && (levels[i-1] == 1))
 {
 if((gap > PULSE_MIN) && (gap < PULSE_MAX))
 { 
 
 }
 else
 {
 decodingOk = false;
#ifdef DEBUG 
 Serial.println(""); Serial.print(F("Wrong pulse length:")); Serial.println(gap, DEC); 
#endif 
 }
 }
 //space
 else if(decodingOk && (levels[i-1] == 0))
 {
 //one
 if((gap > SPACE_ONE_MIN) && (gap < SPACE_ONE_MAX))
 {
 decodedData[len++] = true;
 }
 //zero
 else if((gap > SPACE_ZERO_MIN) && (gap < SPACE_ZERO_MAX))
 {
 decodedData[len++] = false;
 }
 else
 {
 decodingOk = false;
#ifdef DEBUG 
 Serial.println(""); Serial.print(F("Wrong space length:")); Serial.println(gap, DEC); 
#endif 
 }
 } 
 }
 }

if(len > 0)
 {
 analyzeDecodedData(len);
 }
 
 receives = 0;
 
 interrupts();
}

//------------------------- analyze decoded data and make decision that received packet is that what is expected -------------------
void analyzeDecodedData(int len)
{
#ifdef DEBUG 
 for(int i=0;i<len;i++)
 {
 Serial.print(decodedData[i] ? "1|" : "0|");
 }
 Serial.println("");
 Serial.print(F("Decoded ")); Serial.print(len); Serial.println(F("bytes")); 
#endif
 //temp packet?
 if(len == 28)
 { 
 uint32_t raw = 0;

//put all bits into one double word
 for(int i=0;i<28;i++)
 {
 raw |= ((uint32_t)decodedData[i]) << 27-i;
 }

//calculate and compare checksum
 if(checksum(raw))
 {
 #ifdef DEBUG 
 Serial.print(F("Temp received. Raw=0x")); Serial.println(raw,HEX);
 #endif 
 //retrieve channel and temperature data
 int channel = (raw >> 2) & 3;
 int temp = (raw >> 4) & 0xFFF;

#ifdef DEBUG 
 Serial.print(F("Channel="));Serial.print(channel); Serial.print(F(";Temp=")); Serial.print(temp); Serial.println(F("C"));
#endif 
 //
 if(channel == SELECTED_CHANNEL)
 {
 setOutdoorTemp(temp); 
 }
 }
 else
 Serial.println(F("Checksum error")); 
 }
}

//----------------------------------------- checksum ---------------------------------------------
bool checksum(uint32_t data)
{
 byte packetChecksum = (data >> 24) & 0xF;
 byte calcChecksum = 0xF;
 
 for(int i=0;i<6;i++)
 {
 calcChecksum += (data >> (20 - 4*i)) & 0xF;
 }

calcChecksum &= 0xF;

return calcChecksum == packetChecksum; 
}

//----------------------------------------- outdoor temperature set ---------------------------------------------
void setOutdoorTemp(int temp)
{
 outdoorTemp = (float)temp / 10;
 
 Serial.print("OutdoorTemp=");Serial.print(outdoorTemp,DEC);Serial.println("C");
}

 

 

 

Arduino Receiving Tunex temperature / humidity sensor using RFlink Gateway

 

Receiving Tunex temperature / humidity sensor using RFlink

=150,3810,390,870,420,870,390,1860,390,900,390,870,390,1860,390,900,390,1860,390,1860,390,870,390,900,390,870,390,870,390,900,390,870,390,1860,390,900,390,870,390,1860,390,870,390,1860,390,1860,390,900,390,870,390,1860,390,1860,390,1860,420,1860,420,870,390,900,390,870,390,1860,420,870,390,900,390,870,390,900,390,3810,390,900,390,900,390,1860,390,870,390,870,420,1860,390,870,390,1860,390,1860,390,900,390,870,390,870,390,870,390,870,390,870,420,1830,390,870,420,870,390,1830,420,870,420,1830,390,1830,420,870,390,870,390,1860,420,1830,390,1830,420,1830,390,870,420,870,420,870,390,1830,420,870,390,870,420,870,390,870,420,3810,390,870,390,870,420,1830,390,870,390,870,420,1860,390,870,390,1860,390,1860,390,870,390,870,390,870,390,870,390,870,390,870,390,1860,390,870,420,870,390,1860,390,870,390,1860,390,1860,390,870,390,870,390,1860,390,1860,390,1860,390,1860,390,870,390,870,390,870,420,1860,390,870,390,870,390,870,390,870,390,3810,390,870,390,870,420,1830,390,870,390,870,390,1860,390,870,390,1860,390,1860,390,870,390,870,390,870,390,870,390,870,420,870,390,1860,390,870,390,900,390,1860,420,870,390,1860,390,1860,390,900,390,870,420,1860,390,1860,420,1830,390,1860,390,870,390,870,390,870,420,1860,390,870,390,870,390,870,390,870,420,3810,390,870,390,870,390,1860,390,870,390,870,390,1860,420,870,390,1860,390,1860,420,870,390,870,420,870,390,870,390,870,390,870,390,1860,390,870,390,870,390,1860,390,870,390,1860,420,1860,390,870,390,870,390,1860,390,1860,390,1860,390,1860,390,870,390,870,390,870,390,1860,390,870,420,870,390,870,390,870,390,3810,390,870,390,870,390,1860,390,870,390,870,390,1860,420,870,390,1860,420,1860,390,870,390,870,420,870,390,870,390,870,390,870,390,1860,390,870,390,870,420,1860,390,870,390,1860,390,1860,390,870,420,870,390,1860,420,1860,390,1860,390,1860,390,870,390,870,420,870,390,1860,390,870,390,1110,390,870,390,870,390,3810,390,870,390,870,420,1860,390,870,390,870,420,1860,390,870,390,1860,390,1860,390,870,390,870,390,870,420,870,390,900,390,870,420,1860,390,870,420,870,390,1860,420,870,390,1860,390,1860,390,870,390,870,390,1860,390,1860,390,1860,420,1860,390,870,420,870,420,870,390,1860,420;

20;48;Tunex;ID=2501;TEMP=012c;HUM=16;BAT=OK;

 

 

 

Arduino sending and receiving a wide range of common remote switches, certain types of weather station data

— UNTESTED —

https://bitbucket.org/fuzzillogic/433mhzforarduino/wiki/Home

 

433MHz for Arduino
This package contains several small libraries for Arduino 1.0 which add communication capability with some radio controlled (433MHz / 434MHz) domestic appliances. The libraries can be used for easy home automation using cheap, off-the-shelf components.

Features

Support for sending and receiving a wide range of common remote switches.
Support for sending and receiving of certain types of weather station data.
Interrupt based, which allows for multi-tasking sketches.
Very light-weight and fast, leaving plenty of room (CPU-time, RAM and Flash) for other tasks.
Well documented, easy to use, many ready-to-try examples.

 

Receiver:

 

/*
 * This sketch demonstrates how to use InterruptChain to receive and
 * decode remote switches (old and new) and remote sensors.
 *
 * Basically, this sketch combines the features of the ShowReceivedCode
 * and ShowReceivedCodeNewKaku examples of RemoteSwitch and the
 * ThermoHygroReceiver of RemoteSensor all at the same time!
 *
 * After uploading, enable the serial monitor at 115200 baud.
 * When you press buttons on a 433MHz remote control, as supported by 
 * RemoteSwitch or NewRemoteSwitch, the code will be echoed.
 * At the same time, if data of a remote thermo/hygro-sensor is
 * received, as supported by RemoteSensor, it will be echoed as well.
 *
 * Setup:
 * - connect a 433MHz receiver on digital pin 2.
 */

#include <RemoteReceiver.h>
#include <NewRemoteReceiver.h>
#include <SensorReceiver.h>
#include <InterruptChain.h>

void setup() {
 Serial.begin(115200);

// Interrupt -1 to indicate you will call the interrupt handler with InterruptChain
 RemoteReceiver::init(-1, 2, showOldCode);

// Again, interrupt -1 to indicate you will call the interrupt handler with InterruptChain
 NewRemoteReceiver::init(-1, 2, showNewCode);

// And once more, interrupt -1 to indicate you will call the interrupt handler with InterruptChain
 SensorReceiver::init(-1, showTempHumi);

// Set interrupt mode CHANGE, instead of the default LOW.
 InterruptChain::setMode(0, CHANGE);

// On interrupt, call the interrupt handlers of remote and sensor receivers
 InterruptChain::addInterruptCallback(0, RemoteReceiver::interruptHandler);
 InterruptChain::addInterruptCallback(0, NewRemoteReceiver::interruptHandler);
 InterruptChain::addInterruptCallback(0, SensorReceiver::interruptHandler);
}

void loop() {
 // You can do other stuff here!
}

// shows the received code sent from an old-style remote switch
void showOldCode(unsigned long receivedCode, unsigned int period) {
 // Print the received code.
 Serial.print("Code: ");
 Serial.print(receivedCode);
 Serial.print(", period: ");
 Serial.print(period);
 Serial.println("us.");
}

// Shows the received code sent from an new-style remote switch
void showNewCode(NewRemoteCode receivedCode) {
 // Print the received code.
 Serial.print("Addr ");
 Serial.print(receivedCode.address);

if (receivedCode.groupBit) {
 Serial.print(" group");
 } 
 else {
 Serial.print(" unit ");
 Serial.print(receivedCode.unit);
 }

switch (receivedCode.switchType) {
 case NewRemoteCode::off:
 Serial.print(" off");
 break;
 case NewRemoteCode::on:
 Serial.print(" on");
 break;
 case NewRemoteCode::dim:
 Serial.print(" dim");
 Serial.print(receivedCode.dimLevel);
 break;
 }

if (receivedCode.dimLevelPresent) {
 Serial.print(", dim level ");
 Serial.print(receivedCode.dimLevel);
 }

Serial.print(", period: ");
 Serial.print(receivedCode.period);
 Serial.println("us.");
}

// Shows the received sensor data
void showTempHumi(byte *data) {
 // is data a ThermoHygro-device?
 if ((data[3] & 0x1f) == 0x1e) {
 // Yes!
 byte channel, randomId;
 int temp;
 byte humidity;

// Decode the data
 SensorReceiver::decodeThermoHygro(data, channel, randomId, temp, humidity);

// Print temperature. Note: temp is 10x the actual temperature!
 Serial.print("Temperature: ");
 Serial.print(temp / 10); // units
 Serial.print('.');
 Serial.println(temp % 10); // decimal
 }
}

 

 

 

Arduino Manchester encoding library for RF links

 

https://code.google.com/archive/p/mysudoku/downloads

https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mysudoku/manchester.zip

 

Transmitter code:

#include <MANCHESTER.h>

#define TxPin 5 //the digital pin to use to transmit data

unsigned int Tdata = 0; //the 16 bits to send

void setup() 
{ 
MANCHESTER.SetTxPin(TxPin); // sets the digital pin as output default 4
}//end of setup

void loop() 
{
 Tdata +=1;
 MANCHESTER.Transmit(Tdata);
 delay(1000);
}//end of loop

 

Receiver code:

 

#include <MANCHESTER.h>

#define RxPin 2

void setup() 
{ 
 MANCHESTER.SetRxPin(RxPin); //user sets rx pin default 4
 MANCHESTER.SetTimeOut(1000); //user sets timeout default blocks
 Serial.begin(9600); // Debugging only
}//end of setup

void loop() 
{
 unsigned int data = MANCHESTER.Receive();
 Serial.println(data);
}//end of loop

 

Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links
Arduino Manchester encoding library for RF links