Initial commit
This commit is contained in:
commit
f83dd4f105
36 changed files with 3704 additions and 0 deletions
183
lib/SensorTransmitter/SensorTransmitter.cpp
Normal file
183
lib/SensorTransmitter/SensorTransmitter.cpp
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* RemoteSensor library v1.0.2 (20130601) for Arduino 1.0
|
||||
*
|
||||
* This library encodes, encrypts en transmits data to
|
||||
* remote weather stations made by Hideki Electronics..
|
||||
*
|
||||
* Copyright 2011-2013 by Randy Simons http://randysimons.nl/
|
||||
*
|
||||
* Parts of this code based on Oopsje's CrestaProtocol.pdf, for which
|
||||
* I thank him very much!
|
||||
*
|
||||
* License: GPLv3. See license.txt
|
||||
*/
|
||||
|
||||
#include <SensorTransmitter.h>
|
||||
|
||||
|
||||
|
||||
/*******************
|
||||
* Sensor base class
|
||||
******************/
|
||||
|
||||
SensorTransmitter::SensorTransmitter(byte transmitterPin, byte randomId) {
|
||||
_transmitterPin = transmitterPin;
|
||||
_randomId = randomId;
|
||||
|
||||
pinMode(_transmitterPin, OUTPUT);
|
||||
}
|
||||
|
||||
/* Encrypt data byte to send to station */
|
||||
byte SensorTransmitter::encryptByte(byte b) {
|
||||
byte a;
|
||||
for(a=0; b; b<<=1) {
|
||||
a^=b;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* The second checksum. Input is OldChecksum^NewByte */
|
||||
byte SensorTransmitter::secondCheck(byte b) {
|
||||
byte c;
|
||||
if (b&0x80) {
|
||||
b^=0x95;
|
||||
}
|
||||
c = b^(b>>1);
|
||||
if (b&1) {
|
||||
c^=0x5f;
|
||||
}
|
||||
if (c&1) {
|
||||
b^=0x5f;
|
||||
}
|
||||
return b^(c>>1);
|
||||
}
|
||||
|
||||
/* Example to encrypt a package for sending,
|
||||
Input: Buffer holds the unencrypted data.
|
||||
Returns the number of bytes to send,
|
||||
Buffer now holds data ready for sending.
|
||||
*/
|
||||
byte SensorTransmitter::encryptAndAddCheck(byte *buffer) {
|
||||
byte cs1,cs2,count,i;
|
||||
|
||||
count=(buffer[2]>>1) & 0x1f;
|
||||
cs1=0;
|
||||
cs2=0;
|
||||
for(i=1; i<count+1; i++) {
|
||||
buffer[i]=encryptByte(buffer[i]);
|
||||
cs1^=buffer[i];
|
||||
cs2 =secondCheck(buffer[i]^cs2);
|
||||
}
|
||||
buffer[count+1]=cs1;
|
||||
buffer[count+2]=secondCheck(cs1^cs2);
|
||||
return count+3;
|
||||
}
|
||||
|
||||
/* Send one byte and keep the transmitter ready to send the next */
|
||||
void SensorTransmitter::sendManchesterByte(byte transmitterPin, byte b) {
|
||||
byte i;
|
||||
|
||||
// Send start-bit 0.
|
||||
digitalWrite(transmitterPin, LOW);
|
||||
delayMicroseconds(500);
|
||||
digitalWrite(transmitterPin, HIGH);
|
||||
delayMicroseconds(500);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (b&1) {
|
||||
digitalWrite(transmitterPin, HIGH);
|
||||
} else {
|
||||
digitalWrite(transmitterPin, LOW);
|
||||
}
|
||||
|
||||
delayMicroseconds(500); /* 500uS delay */
|
||||
|
||||
b=~b;
|
||||
if (i&1) {
|
||||
b>>=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send bytes (prepared by “encryptAndAddCheck”) and pause at the end. */
|
||||
void SensorTransmitter::sendManchesterPackage(byte transmitterPin, byte *data, byte cnt) {
|
||||
byte i;
|
||||
|
||||
for (i=0; i<cnt; i++) {
|
||||
sendManchesterByte(transmitterPin, data[i]);
|
||||
}
|
||||
|
||||
digitalWrite(transmitterPin, LOW); /* Drop the transmitter line */
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts, adds checksums and transmits the data. The value of byte 3 in the data is ignored.
|
||||
*/
|
||||
void SensorTransmitter::sendPackage(byte transmitterPin, byte *data) {
|
||||
byte buffer[14], temp, count;
|
||||
for (temp=0x40; temp>=0x40; temp+=0x40) { /* Sends 3 packages */
|
||||
memcpy(buffer, data, ((data[2] >> 1) & 0x1f) + 1);
|
||||
|
||||
buffer[3] = (buffer[3] & 0x1f) + temp;
|
||||
|
||||
count = encryptAndAddCheck(buffer); /* Encrypt, add checksum bytes */
|
||||
sendManchesterPackage(transmitterPin, buffer,count); /* Send the package */
|
||||
|
||||
delay(30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* Thermo / Hygro sensor transmitter
|
||||
***********************************/
|
||||
|
||||
ThermoHygroTransmitter::ThermoHygroTransmitter(byte transmitterPin, byte randomId, byte channel) : SensorTransmitter(transmitterPin, randomId) {
|
||||
_channel = channel;
|
||||
}
|
||||
|
||||
void ThermoHygroTransmitter::sendTempHumi(int temperature, byte humidity) {
|
||||
byte buffer[10];
|
||||
|
||||
// Note: temperature is 10x the actual temperature! So, 23.5 degrees is passed as 235.
|
||||
|
||||
buffer[0] = 0x75; /* Header byte */
|
||||
buffer[1] = (_channel << 5) | _randomId ; /* Thermo-hygro at channel 1 (see table1)*/
|
||||
buffer[2] = 0xce; /* Package size byte for th-sensor */
|
||||
buffer[3] = 0x1e; /* Themo/Hygro */
|
||||
|
||||
if ( temperature < 0 ) {
|
||||
buffer[5] = 0x4 << 4; // High nibble is 0x4 for sub zero temperatures...
|
||||
temperature = -temperature; // Make temperature positive
|
||||
} else {
|
||||
buffer[5] = 0xc << 4; // ...0xc for positive
|
||||
}
|
||||
|
||||
// Note: temperature is now always positive!
|
||||
buffer[4] = (((temperature % 100) / 10 ) << 4) | // the "3" from 23.5
|
||||
(temperature % 10); // the "5" from 23.5
|
||||
buffer[5] |= (temperature / 100); // the "2" from 23.5
|
||||
|
||||
buffer[6] = ((humidity / 10) << 4) | (humidity % 10); // BCD encoded
|
||||
|
||||
buffer[7]=0xff; /* Comfort flag */
|
||||
|
||||
sendPackage(_transmitterPin, buffer);
|
||||
}
|
||||
|
||||
void ThermoHygroTransmitter::sendRainlevel(unsigned int level){ // in 0.7mm
|
||||
byte buffer[10];
|
||||
|
||||
// Note: temperature is 10x the actual temperature! So, 23.5 degrees is passed as 235.
|
||||
|
||||
buffer[0] = 0x75; /* Header byte */
|
||||
buffer[1] = (_channel << 5) | _randomId ; /* Thermo-hygro at channel 1 (see table1)*/
|
||||
buffer[2] = 0xcc; /* Package size byte for rain-sensor */
|
||||
buffer[3] = 0x0e; /* Rain level */
|
||||
|
||||
// Note: temperature is now always positive!
|
||||
buffer[4] = level & 0xff; // Low byte
|
||||
buffer[5] = (level >>8) & 0xff; // High byte
|
||||
|
||||
sendPackage(_transmitterPin, buffer);
|
||||
}
|
||||
112
lib/SensorTransmitter/SensorTransmitter.h
Normal file
112
lib/SensorTransmitter/SensorTransmitter.h
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* RemoteSensor library v1.0.2 (20130601) for Arduino 1.0
|
||||
*
|
||||
* This library encodes, encrypts en transmits data to
|
||||
* remote weather stations made by Hideki Electronics..
|
||||
*
|
||||
* Copyright 2011-2013 by Randy Simons http://randysimons.nl/
|
||||
*
|
||||
* Parts of this code based on Oopsje's CrestaProtocol.pdf, for which
|
||||
* I thank him very much!
|
||||
*
|
||||
* License: GPLv3. See license.txt
|
||||
*/
|
||||
|
||||
#ifndef SensorTransmitter_h
|
||||
#define SensorTransmitter_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* SensorTransmitter provides a generic class to simulate Cresta weather sensors, for use
|
||||
* with Cresta weather stations.
|
||||
* E.g. http://www.cresta.nl/index.php?Itemid=2&option=com_zoo&view=item&category_id=32&item_id=281&lang=en
|
||||
*
|
||||
* Cresta is just a brand name. The original OEM seems to be Hideki Electronics. There are
|
||||
* other brands which use the same hardware and / or protocol. As far as I know these include
|
||||
* Mebus, Irox, Honeywell, Cresta and RST.
|
||||
*
|
||||
* Hardware required for this library: a 433MHz/434MHz SAW oscillator transmitter, e.g.
|
||||
* http://www.sparkfun.com/products/10534
|
||||
* http://www.conrad.nl/goto/?product=130428
|
||||
*/
|
||||
class SensorTransmitter {
|
||||
public:
|
||||
/**
|
||||
* Initializes the transmitter. About the random id: "A sensor selects a random value
|
||||
* in the range of column 1 when it is reset. It keeps the same ID until it is reset again."
|
||||
* You can leave it at 0 for most purposes
|
||||
* The transmitter pin is set in OUTPUT mode; you don't have to do this yourself.
|
||||
*
|
||||
* @param transmitterPin Arduino-pin connected to the 433MHz transmitter
|
||||
* @param randomId A "random" value in the range [0..31]
|
||||
*/
|
||||
SensorTransmitter(byte transmitterPin, byte randomId);
|
||||
|
||||
/**
|
||||
* Sends a raw sensor package. Before transmitting, the data is encrypted and checksums are
|
||||
* added. The buffer of the data doesn't need to have room for the checksums, as the data is
|
||||
* copied internally to a new buffer which is always large enough.
|
||||
* However, the data must be valid!
|
||||
*
|
||||
* The data is transmitted 3 times.
|
||||
*
|
||||
* Note that this is a static method.
|
||||
*
|
||||
* @param transmitterPin Arduino-pin connected to the 433MHz transmitter
|
||||
* @param data Pointer to data to transmit
|
||||
*/
|
||||
static void sendPackage(byte transmitterPin, byte *data);
|
||||
|
||||
protected:
|
||||
byte _transmitterPin;
|
||||
byte _randomId;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Sends data as manchester encoded stream
|
||||
*/
|
||||
static void sendManchesterPackage(byte transmitterPin, byte *data, byte cnt);
|
||||
|
||||
/**
|
||||
* Sends a single byte as manchester encoded stream
|
||||
*/
|
||||
static void sendManchesterByte(byte transmitterPin, byte b);
|
||||
|
||||
/**
|
||||
* Encryption and checksum
|
||||
*/
|
||||
static byte encryptAndAddCheck(byte *buffer);
|
||||
static byte secondCheck(byte b);
|
||||
static byte encryptByte(byte b);
|
||||
};
|
||||
|
||||
class ThermoHygroTransmitter : public SensorTransmitter {
|
||||
public:
|
||||
/**
|
||||
* Mimics a Thermo / Hygro sensor. The channel of this device can be 1..5, but note
|
||||
* that only the more expensive receivers can use channels 4 and 5. However, for use
|
||||
* in conjunction with SensorReceiver this is of no concern.
|
||||
*
|
||||
* @param transmitterPin Arduino-pin connected to the 433MHz transmitter
|
||||
* @param randomId A "random" value in the range [0..31]
|
||||
* @channel The channel of this sensor, range [1..5]
|
||||
* @see SensorTransmitter::SensorTransmitter (constructor)
|
||||
*/
|
||||
ThermoHygroTransmitter(byte transmitterPin, byte randomId, byte channel);
|
||||
|
||||
/**
|
||||
* Sends temperature and humidity.
|
||||
*
|
||||
* @param temperature 10x the actual temperature. You want to send 23,5 degrees, then temperature should be 235.
|
||||
* @param humidty Humidity in percentage-points REL. Thus, for 34% REH humidity should be 34.
|
||||
*/
|
||||
void sendTempHumi(int temperature, byte humidity);
|
||||
void sendRainlevel(unsigned int level); // in 0.7mm
|
||||
|
||||
private:
|
||||
byte _channel; // Note: internally, the channels for the thermo/hygro-sensor are mapped as follow:
|
||||
// 1=>1, 2=>2, 3=>3, 4=>5, 5=>6.
|
||||
// This because interally the rain sensor, UV sensor and anemometer are on channel 4.
|
||||
};
|
||||
#endif
|
||||
28
lib/SensorTransmitter/examples/ThermoHygroTransmitter.ino
Normal file
28
lib/SensorTransmitter/examples/ThermoHygroTransmitter.ino
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* This sketch sends (bogus) thermo / hygro data to a remote weather sensors made by Cresta.
|
||||
*
|
||||
* Setup:
|
||||
* - connect transmitter input of a 433MHz transmitter to digital pin 11
|
||||
* - On the weather station, activate the "scan" function for channel 1.
|
||||
*/
|
||||
|
||||
#include <SensorTransmitter.h>
|
||||
|
||||
// Initializes a ThermoHygroTransmitter on pin 11, with "random" ID 0, on channel 1.
|
||||
ThermoHygroTransmitter transmitter(4, 0, 1);
|
||||
|
||||
void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Displays temperatures from -10 degrees Celsius to +20,
|
||||
// and humidity from 10% REL to 40% REL, with increments of 2
|
||||
for (int i = -10; i<=20; i+=2) {
|
||||
// Temperatures are passed at 10 times the real value,
|
||||
// to avoid using floating point math.
|
||||
transmitter.sendTempHumi(i * 10, i + 20);
|
||||
|
||||
// Wait two seconds before sending next.
|
||||
delay(2000);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue