I have a need to monitor and log temperature and humidity in several places in my house and I have wired up 3 AM2302 DHT sensors in the attic.
But now I also need to connect to a few extra sensors that cannot be wired in to the ESP-07 unit, so I cannot use the DHT sensors. So I figured that if I use commercial wireless sensors operating on 433MHz it could be possible to connect to them and read the data over 433MHz.
Is there some libraries for 433MHz receivers (note: I am not looking for transmitters) that can be used for ESP8266?
And are there any tutorials for that kind of project?
I assume there are two different steps that need to be taken:
Connecting a 433MHz receiver to the ESP8266 to get the digital data stream
Decoding the incoming data to extract the wanted information (temperature and humidity)
Grateful for any suggestions!
BTW: I attach a picture of the 433MHz receiver I have.
Returning to this (unanswered) issue:
I have found that there is an Arduino library named rc-switch for controlling wireless mains switches using a 433 MHz transmitter. This library also has a way to enable a 433 MHz receiver to read and decode data off the air.
It seems like this library is not targeting an ESP8266 module as the host, though, so I would like to know if there is some experience using it with for example an ESP-07, ESP-12 or ESP-01. I am specifically looking for ways to connect the Tx and Rx devices into the ESP module correctly.
I am looking for reading Dallas weather station data over 433 MHz and posting them to a website database for logging purposes and also for setting up an electrical switch home automation system.
If that sensor use fine offset protocol to send the temperature this might work:
But you have to make a few changes to make it run on esp.
i did play around with it and got it to work but not with wifi enabled at the same time.
maybe give it a try and if it can receive what you need use it as a starting point.
//WeatherSensorWH2 from https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino
//WeatherSensorWH2 adapted for esp8266 by me.
// ------------------begin ESP8266'centric----------------------------------
//from https://www.hackster.io/rayburne/esp8266-turn-off-wifi-reduce-current-big-time-1df8ae
#define FREQUENCY 160 // valid 80, 160
//
#include "ESP8266WiFi.h"
extern "C" {
#include "user_interface.h"
// ------------------end ESP8266'centric------------------------------------
uint16_t interval_us = 200;
volatile unsigned long counter=0;
#define RF_IN 3
// For better efficiency, the port is read directly
// the following two lines should be changed appropriately
// if the line above is changed.
// 1 is indicated by 500uS pulse
// wh2_accept from 2 = 400us to 3 = 600us
#define IS_HI_PULSE(interval) (interval >= 2 && interval <= 5) //#define IS_HI_PULSE(interval) (interval >= 2 && interval <= 3) original
// 0 is indicated by ~1500us pulse
// wh2_accept from 7 = 1400us to 8 = 1600us
#define IS_LOW_PULSE(interval) (interval >= 6 && interval <= 8) //#define IS_LOW_PULSE(interval) (interval >= 7 && interval <= 8) original
// worst case packet length
// 6 bytes x 8 bits x (1.5 + 1) = 120ms; 120ms = 200us x 600
#define HAS_TIMED_OUT(interval) (interval > 600)
// we expect 1ms of idle time between pulses
// so if our pulse hasn't arrived by 1.2ms, reset the wh2_packet_state machine
// 6 x 200us = 1.2ms
#define IDLE_HAS_TIMED_OUT(interval) (interval > 6)
// our expected pulse should arrive after 1ms
// we'll wh2_accept it if it arrives after
// 4 x 200us = 800us
#define IDLE_PERIOD_DONE(interval) (interval >= 4)
// Shorthand for tests
#define RF_HI (digitalRead(RF_IN) == HIGH)
#define RF_LOW (digitalRead(RF_IN) == LOW)
// wh2_flags
#define GOT_PULSE 0x01
#define LOGIC_HI 0x02
volatile byte wh2_flags = 0;
volatile byte wh2_packet_state = 0;
volatile int wh2_timeout = 0;
byte wh2_packet[5];
byte wh2_calculated_crc;
void inline handler (void){
timer0_write(ESP.getCycleCount() + interval_us * 160); // 160 when running at 160mhz
static byte sampling_state = 0;
static byte count;
static boolean was_low = false;
counter++;
switch(sampling_state) {
case 0: // waiting
wh2_packet_state = 0;
if (RF_HI) {
if (was_low) {
count = 0;
sampling_state = 1;
was_low = false;
}
} else {
was_low = true;
}
break;
case 1: // acquiring first pulse
count++;
// end of first pulse
if (RF_LOW) {
if (IS_HI_PULSE(count)) {
wh2_flags = GOT_PULSE | LOGIC_HI;
sampling_state = 2;
count = 0;
} else if (IS_LOW_PULSE(count)) {
wh2_flags = GOT_PULSE; // logic low
sampling_state = 2;
count = 0;
} else {
sampling_state = 0;
}
}
break;
case 2: // observe 1ms of idle time
count++;
if (RF_HI) {
if (IDLE_HAS_TIMED_OUT(count)) {
sampling_state = 0;
} else if (IDLE_PERIOD_DONE(count)) {
sampling_state = 1;
count = 0;
}
}
break;
}
if (wh2_timeout > 0) {
wh2_timeout++;
if (HAS_TIMED_OUT(wh2_timeout)) {
wh2_packet_state = 0;
wh2_timeout = 0;
}
}
}
}
void setup() {
pinMode(RF_IN, INPUT);
/* Initializations */
// ------------------begin ESP8266'centric----------------------------------
WiFi.forceSleepBegin(); // turn off ESP8266 RF
delay(1); // give RF section time to shutdown
system_update_cpu_freq(FREQUENCY);
// ------------------end ESP8266'centric------------------------------------
//Serial.begin(115200);
Serial.begin(57600, SERIAL_8N1, SERIAL_TX_ONLY );
Serial.println("Weather Sensor WH2 Test ");
noInterrupts();
timer0_isr_init();
timer0_attachInterrupt(handler);
timer0_write(ESP.getCycleCount() + interval_us * 160); // 160 when running at 160mhz
interrupts();
//------------------------wh2 end-------------------------------------------------
}
void loop() {
wdt_reset();
wh2_stuff();
}
void wh2_stuff()
{
if(counter>25000)
{
counter=0;
Serial.print(".");
}
static unsigned long old = 0, packet_count = 0, bad_count = 0, average_interval;
unsigned long spacing, now;
byte i;
if (wh2_flags) {
if (wh2_accept()) {
// calculate the CRC
wh2_calculate_crc();
now = millis();
spacing = now - old;
old = now;
packet_count++;
average_interval = now / packet_count;
if (!wh2_valid()) {
bad_count++;
}
// flash green led to say got packet
Serial.println("");
for(i=0;i<5;i++) {
Serial.print("0x");
Serial.print(wh2_packet[i], HEX);
Serial.print("/");
Serial.print(wh2_packet[i], DEC);
Serial.print(" ");
}
Serial.print("| Sensor ID: ");
Serial.print(wh2_sensor_id());
Serial.print(" | ");
Serial.print(wh2_humidity());//batt
Serial.print("v | ");
Serial.print(wh2_temperature(), DEC);
Serial.print(" | ");
Serial.print((wh2_valid() ? "OK" : "BAD"));
Serial.print(" | packet_count ");
Serial.println(packet_count);
}
wh2_flags = 0x00;
}
}
// processes new pulse
boolean wh2_accept()
{
static byte packet_no, bit_no, history;
// reset if in initial wh2_packet_state
if(wh2_packet_state == 0) {
// should history be 0, does it matter?
history = 0xFF;
wh2_packet_state = 1;
// enable wh2_timeout
wh2_timeout = 1;
} // fall thru to wh2_packet_state one
// acquire preamble
if (wh2_packet_state == 1) {
// shift history right and store new value
history <<= 1;
// store a 1 if required (right shift along will store a 0)
if (wh2_flags & LOGIC_HI) {
history |= 0x01;
}
// check if we have a valid start of frame
// xxxxx110
if ((history & B00000111) == B00000110) {
// need to clear packet, and counters
packet_no = 0;
// start at 1 becuase only need to acquire 7 bits for first packet byte.
bit_no = 1;
wh2_packet[0] = wh2_packet[1] = wh2_packet[2] = wh2_packet[3] = wh2_packet[4] = 0;
// we've acquired the preamble
wh2_packet_state = 2;
}
return false;
}
// acquire packet
if (wh2_packet_state == 2) {
wh2_packet[packet_no] <<= 1;
if (wh2_flags & LOGIC_HI) {
wh2_packet[packet_no] |= 0x01;
}
bit_no ++;
if(bit_no > 7) {
bit_no = 0;
packet_no ++;
}
if (packet_no > 4) {
// start the sampling process from scratch
wh2_packet_state = 0;
// clear wh2_timeout
wh2_timeout = 0;
return true;
}
}
return false;
}
void wh2_calculate_crc()
{
wh2_calculated_crc = crc8(wh2_packet, 4);
}
bool wh2_valid()
{
return (wh2_calculated_crc == wh2_packet[4]);
}
int wh2_sensor_id()
{
return (wh2_packet[0] << 4) + (wh2_packet[1] >> 4);
}
byte wh2_humidity()
{
return wh2_packet[3];
}
/* Temperature in deci-degrees. e.g. 251 = 25.1 */
int wh2_temperature()
{
int temperature;
temperature = ((wh2_packet[1] & B00000111) << 8) + wh2_packet[2];
// make negative
if (wh2_packet[1] & B00001000) {
temperature = -temperature;
}
return temperature;
}
uint8_t crc8( uint8_t *addr, uint8_t len)
{
uint8_t crc = 0;
// Indicated changes are from reference CRC-8 function in OneWire library
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01
crc <<= 1; // changed from right shift
if (mix) crc ^= 0x31;// changed from 0x8C;
inbyte <<= 1; // changed from right shift
}
}
return crc;
}
i ran this on a esp-01
That receiver you have might need 5v to play nice, level shifter or voltage divider maybe?
Best of luck
As for the rc-switch library i can confirm that its working to transmit on esp8266/32, i think i tried the receiver part too but if i remember right it did not work well with wifi enabled.
And depending on the used protocol you have to change in RCSwitch.cpp to make it play nice
const unsigned int RCSwitch::nSeparationLimit = 2200;// was 4300
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
// according to discussion on issue #14 it might be more suitable to set the separation
// limit to the same time as the 'low' part of the sync signal for the current protocol.
that was for using protocol 4...
the esp-01 are so cheap so im am considering to use one esp8266 with wifi disabled as a reciever and just send the data to another esp8266 over serial
have fun
OK thanks, so the planned use case for logging weather data is not really going to work since I was thinking of using the ESP-07 as a gateway between the temp/humid data and my weather database on my website. A HTTP post to the website via WiFi is the main thing there....
The transmitter side for home automation seems an easier case then?
But what about pin selections on the ESP in rc-switch library? How can I determine this?
I see in the example code for BetterWH2: #define RF_IN 3
Does this refer to GPIO3?
How is the same done for rc-switch?
void setup() {
pinMode(RF_IN, INPUT);
/* Initializations */
// ------------------begin ESP8266'centric----------------------------------
WiFi.forceSleepBegin(); // turn off ESP8266 RF
delay(1); // give RF section time to shutdown
system_update_cpu_freq(FREQUENCY);
// ------------------end ESP8266'centric------------------------------------
This shows that WiFi is switched off in setup().
Is it needed? Would it not stay off if one does not start WiFi in setup?
In my application I had planned to use deepsleep to make the device power up at regular intervals (1 hour) and then monitor for the 433 MHz weather data until they arrive (the weather station sends intermittently).
So maybe I could use this strategy:
First make sure WiFi is off in setup() as shown by you.
Then call a 433 MHz listen function to read the weather data.
Then once it has finished its job and the data are in memory, switch on WiFi.
Finally once WiFi is connected send off the data to the webserver and go back to deep sleep.
Possibly switching off WiFi before deep sleep...
When running the 433 receiver I plan on switching its power on/off with a transistor from 5V and use a resistor divider on the data output to get the signal level to 3V. The system will run on batteries...
Questions:
Can the ESP8266 be configured to NOT start up WiFi when it wakes up from deepsleep? It ssems like WiFi starts before one gets to the setup() function in my other applications...
Also, can the rc-switch objects be unloaded after use so they do not interfere with WiFi?
KASSIMSAMJI:
you know you'd save much , going for ESP 01, they can talk to each (server-client ) sending data back and forth across several ESP's in your house
My use case is to let an ESP module interface to 433 MHz signalling for two distinct projects:
Reading data from a weather station and sending that via WiFi to my web server. Uses a 433 receiver.
Controlling mains switches operating at 433 MHz for home automation. Uses a 433 MHz transmitter.
Of these the first is the most difficult and is what is being discussed above.
I normally use ESP-07 modules because they have a lot of I/O pins and also an antenna connector for extended range.
I normally use ESP-07 modules because they have a lot of I/O pins and also an antenna connector for extended range.
ESP-01 's are a lot cheaper though and usually not more than 1 or 2 pins are required. Also for home automation i think they are the way to go. You can always solder an antenna onto an ESP-01,
Deva_Rishi:
ESP-01 's are a lot cheaper though and usually not more than 1 or 2 pins are required. Also for home automation i think they are the way to go. You can always solder an antenna onto an ESP-01,
Well, in my electronics store they are the same price (approx $9) and the ESP-07 is shielded (FCC Certified) too.
In fact now that I checked they have a reduced price of -30% this week so I might as well stock up...