Initial commit

This commit is contained in:
Nigreon 2025-02-22 23:32:03 +01:00
commit f83dd4f105
36 changed files with 3704 additions and 0 deletions

View 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);
}

View 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

View 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);
}
}