greenhousino/sensor433-arduino/sensor433-arduino.ino

244 lines
6.1 KiB
C++

/*
RadioHead DHT22 Weather Station
Copyright (c) 2017 Peter Müller <peter@crycode.de> (https://crycode.de)
Source: https://git.cryhost.de/crycode/attiny85-radiohead-dht22-weather-sensor/-/tree/master
*/
/**************
config
**************/
/// RH_ASK works with ATTiny85, using Arduino 1.0.5 and tinycore from
/// https://code.google.com/p/arduino-tiny/downloads/detail?name=arduino-tiny-0100-0018.zip
/// Tested with the examples ask_transmitter and ask_receiver on ATTiny85.
/// Caution: The RAM memory requirements on an ATTiny85 are *very* tight. Even the bare bones
/// ask_transmitter sketch barely fits in eh RAM available on the ATTiny85. Its unlikely to work on
/// smaller ATTinys such as the ATTiny45 etc. If you have wierd behaviour, consider
/// reducing the size of RH_ASK_MAX_PAYLOAD_LEN to the minimum you can work with.
/// Caution: the default internal clock speed on an ATTiny85 is 1MHz. You MUST set the internal clock speed
/// to 8MHz. You can do this with Arduino IDE, tineycore and ArduinoISP by setting the board type to "ATtiny85@8MHz',
/// setting theProgrammer to 'Arduino as ISP' and selecting Tools->Burn Bootloader. This does not actually burn a
/// bootloader into the tiny, it just changes the fuses so the chip runs at 8MHz.
/// If you run the chip at 1MHz, you will get RK_ASK speeds 1/8th of the expected.
///
/// Initialise RH_ASK for ATTiny85 like this:
/// // #include <SPI.h> // comment this out, not needed
/// RH_ASK driver(2000, 4, 3); // 200bps, TX on D3 (pin 2), RX on D4 (pin 3)
/// then:
/// Connect D3 (pin 2) as the output to the transmitter
/// Connect D4 (pin 3) as the input from the receiver.
///
///
/// For testing purposes you can connect 2 Arduino RH_ASK instances directly, by
/// connecting pin 12 of one to 11 of the other and vice versa, like this for a duplex connection:
///
/// \code
/// Arduino 1 wires Arduino 1
/// D11-----------------------------D12
/// D12-----------------------------D11
/// GND-----------------------------GND
/// \endcode
///
/// You can also connect 2 RH_ASK instances over a suitable analog
/// transmitter/receiver, such as the audio channel of an A/V transmitter/receiver. You may need
/// buffers at each end of the connection to convert the 0-5V digital output to a suitable analog voltage.
///
/// Measured power output from RFM85 at 5V was 18dBm.
// pin with the LED connected
#define LED_PIN 4
// blink time for the LED
#define LED_TIME 200
// pin of the DHT22 sensor
#define DHT_PIN 1
// the own RadioHead address
#define RH_OWN_ADDR 0xca // 202
// the server RadioHead address
#define RH_SERVER_ADDR 0x01
// RadioHead bitrate in bit/s
#define RH_SPEED 2000
// pins for the radio hardware
#define RH_RX_PIN 5 // not used, set to a non-existent pin
#define RH_TX_PIN 3
#define RH_PTT_PIN 5 // not used, set to a non-existent pin
/**************
end config
**************/
#include <Arduino.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/delay.h>
// for watchdog wakeup
// https://gist.github.com/dwhacks/8055287
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// DHT22 lib
// not using the current adafruit dht library, because it eats too many memory
#include "dht22.h"
dht22 dht;
#define RH_BUF_LEN 5
uint8_t rh_buf[RH_BUF_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
// reduce the RadioHead max message length to save memory
#define RH_ASK_MAX_MESSAGE_LEN RH_BUF_LEN
// RadioHead
#include <RH_ASK.h>
#define MSG_START 0x00
#define MSG_TEMP 0x01
#define MSG_HUMID 0x02
#define MSG_ERR 0xee
RH_ASK rh_driver(RH_SPEED, RH_RX_PIN, RH_TX_PIN, RH_PTT_PIN);
// watchdog flag
volatile boolean f_wdt = 1;
// temp / humid toggle
volatile boolean toggle = 0;
void gotoSleep(void);
void setup() {
// setup the LED pin
pinMode(LED_PIN, OUTPUT);
// init the DHT22
dht_init(&dht, DHT_PIN);
uint8_t num_blink = 3;
if (!rh_driver.init()) {
num_blink = 5;
}
// blink 3 times
for (uint8_t i = 0; i < num_blink; i++) {
digitalWrite(LED_PIN, HIGH);
_delay_ms(LED_TIME);
digitalWrite(LED_PIN, LOW);
_delay_ms(LED_TIME);
}
// send start message
rh_buf[0] = MSG_START;
rh_send(1);
setup_watchdog(6); // approximately 4 seconds sleep
}
// main loop
void loop() {
if (f_wdt) {
f_wdt = 0;
// turn on the LED
digitalWrite(LED_PIN, HIGH);
// temperature and humidity
float t = 0;//float is 32bit = 1byte
float h = 0;
// read from the sensor and check if it was successfull
if (dht_read_data(&dht, &t, &h) == 1) {
// normal message
if (toggle) {
rh_buf[0] = MSG_TEMP;
memcpy(&rh_buf[1], &t, 4);
} else {
rh_buf[0] = MSG_HUMID;
memcpy(&rh_buf[1],&h,4);
}
toggle = !toggle;
rh_send(RH_BUF_LEN);
} else {
// error message
rh_buf[0] = MSG_ERR;
rh_send(1);
}
// turn off the LED
digitalWrite(LED_PIN, LOW);
system_sleep();
//_delay_ms(1000);
}
}
// function to send RadioHead messages from the buffer
void rh_send(uint8_t len) {
rh_driver.send((uint8_t *)rh_buf, len);
rh_driver.waitPacketSent();
}
ISR(WDT_vect)
{
f_wdt = 1; // set global flag
}
/* set system into the sleep state
system wakes up when watchdog is timed out
*/
void system_sleep() {
cbi(ADCSRA, ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA, ADEN); // switch Analog to Digitalconverter ON
}
/* 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
*/
void setup_watchdog(int ii) {
byte bb;
int ww;
if (ii > 9 ) ii = 9;
bb = ii & 7;
if (ii > 7) bb |= (1 << 5);
bb |= (1 << WDCE);
ww = bb;
MCUSR &= ~(1 << WDRF);
// start timed sequence
WDTCR |= (1 << WDCE) | (1 << WDE);
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}