Hello my fellow coders!
I was working on a sensor to put in every room so I could measure temperature and humidity and therefore thought, that I should get myself some of these weather stations that use the weather1 protocol. But I was like: “Hey, I still got these DHTs and Atmega chips lying around so why not use them?“ And I did. I hereby want to present to you:
The DIY-couple-of-bucks Arduino weather station running on the protocol weather1 which can be recognized by Pimatic’s homeduino without any issues!
Hardware:
- Arduino (or just an Atmega on a breadboard)
- 433MHz Transmitter
- DHT22 (others should work as well)
I personally think it is a good way to enable the community to build cheap sensors which don’t require much parts.
I know my work isn’t perfect as it is, there is lots of stuff that needs to be done like reading battery voltage and transmitting that as well, but here is a first glance at the code:
/**
* Weather1 spoof by Florian Leitmann
* 14th June 2015
* Made for Pimatic
* Tested to work with:
* - FS1000A RF transmitter
* - DHT22 temperature/humidity sensor
* - Homeduino on Pimatic
*/
//include the library to work with the DHT
#include "DHT.h"
//The values below have been identified by the documentation on weather1
#define SIGNAL_BREAK 456
#define SIGNAL_SHORT 1990
#define SIGNAL_LONG 3940
#define SIGNAL_STOP 9236
#define REPEATS 7
#define RFPIN 3 //Pin that the RF transmitter is connected to
#define RFPWRPIN 6 //Pin that the power of the transmitter is connected to
#define DHTPIN 4 //Pin that the DHT data is connected to
#define DHTPWRPIN 5 //Pin that the DHT power is connected to
#define DHTTYPE DHT22 //DHT11 or DHT21 (AM2301) or DHT22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
int MODULE_ID = 1; //Used to identify the module in pimatic (1-255)
int CHANNEL = 1; //Multiple channels can be used (can be 1 - 4)
int TEMP_UNIT = 'C'; //may be set to F
int WAIT_TIME = 10; //in seconds (minimum: 3 secs)
/**
* This is a template of the binary message that will be send encoded
* by pulses of the RF transmitter
* Here is what the bits mean
* 0101 | 11010000 | 00 | 00 | 000100001001 | 00111101
* ? ID BT CH Temp. Humid.
*
* The temperature in this example is 26.5° (but sended at 265) and will
* be decoded in Pimatic again to the correct value.
* The value of the relative humidity is 65%
*/
byte message[] = {
0,1,0,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,1,1,1,1,1
};
void setup() {
pinMode(RFPIN, OUTPUT);
pinMode(RFPWRPIN, OUTPUT);
pinMode(DHTPWRPIN, OUTPUT);
pinMode(13, OUTPUT); //LED Pin
setMessage(MODULE_ID, 4, 11);
setMessage(CHANNEL-1, 14, 15);
dht.begin();
}
/*
* @loop()
* turn on the hardware, send the message (other functions get called)
* to retrieve the data, so look below, then switch the hardware off
* and wait for the next cycle
*/
void loop() {
setHardware(1);
sendMessage();
setHardware(0);
delay((WAIT_TIME-2)*1000); //adjusted due to necessary wait from DHT
}
/*
* @setHardware(byte on_off)
* turn the attached devices either on or off, whatever
* you need right now
*/
void setHardware(byte on_off){
if(on_off == 1){
digitalWrite(DHTPWRPIN, HIGH);
digitalWrite(RFPWRPIN, HIGH);
} else {
digitalWrite(DHTPWRPIN, LOW);
digitalWrite(RFPWRPIN, LOW);
}
}
/*
* @sendBit(byte b)
* takes a given byte which is either 1 or 0 and then sends it
* over the air using the breaks necessary for pimatic to recognize
* the profile of the a weather1 station
*/
void sendBit(byte b) {
if (b == 0) {
digitalWrite(RFPIN, HIGH);
delayMicroseconds(SIGNAL_BREAK);
digitalWrite(RFPIN, LOW);
delayMicroseconds(SIGNAL_SHORT);
}
else {
digitalWrite(RFPIN, HIGH);
delayMicroseconds(SIGNAL_BREAK);
digitalWrite(RFPIN, LOW);
delayMicroseconds(SIGNAL_LONG);
}
}
/*
* @sendTerminator()
* This method sends Arnold Schwarzenegger back in time. Just kidding,
* actually it does deliver the long break to show the end of the
* message[]
*/
void sendTerminator(){
digitalWrite(RFPIN, HIGH);
delayMicroseconds(SIGNAL_BREAK);
digitalWrite(RFPIN, LOW);
delayMicroseconds(SIGNAL_STOP);
digitalWrite(RFPIN, HIGH);
digitalWrite(RFPIN, LOW);
}
/*
* @sendMessage()
* execute the getDHTvalues() method to get some input in the
* message[] and then send the message X times using the sendBit() method
* followed by the terminator pulse
*/
void sendMessage() {
getDHTvalues();
for (byte i = 0; i < REPEATS; i++) {
digitalWrite(13, HIGH); //LED PIN
for (byte i = 0; i < sizeof(message); i++){
sendBit(message[i]);
}
digitalWrite(13, LOW);
sendTerminator();
}
}
/*
* @setMessage(int val, int startPos, int endPos)
* convert an integer to binary representation and
* write the output to the locations specified in the
* message[]
*/
void setMessage(int val, int startPos, int endPos){
int result[12];
int theValue = val;
for (byte i = 0, j = 11; i < 12; ++i, j--) {
result[j] = theValue & (1 << i) ? 1 : 0;
}
for (byte i = endPos, j=11; i > startPos-1; i--,j--){
message[i] = result[j];
}
}
/*
* @getDHTvalues()
* wait for two seconds to read the values of the DHT and
* replace their counterparts in the message[]
*/
void getDHTvalues(){
delay(2000); //DHT needs 2 seconds to get started
int h = (int) dht.readHumidity();
int t;
if(TEMP_UNIT == 'C'){
t = (int) (dht.readTemperature() * 10);
} else {
t = (int) (dht.readTemperature(true) * 10);
}
//if the values could not be red
if (isnan(h) || isnan(t)) {
setMessage(0, 16, 27); //Temperature
setMessage(0, 28, 35); //Humidity
} else {
setMessage(t, 16, 27); //Temperature
setMessage(h, 28, 35); //Humidity
}
}
Listening using the debug mode in Pimatic on the homeduino you receive:
This is how the device is to be configured in Pimatic:
{
"id": "fakeWeather",
"name": "Faked Weather Station",
"class": "HomeduinoRFTemperature",
"protocols": [
{
"name": "weather1",
"options": {
"id": 1,
"channel": 1
}
}
]
}
And once you put the device in Pimatic you will receive such an output:
At this point I would like to thank all of you developers who contribute to this awesome project and hope that somebody else can make some use of project as well. I believe with the method I used to spoof the device, almost any device where we know of the pattern can be replicated.
Thanks, and I’m open for your comments and remarks!
Sincerely,
Overflow