/* RadioHead DHT22 Weather Station Copyright (c) 2017 Peter Müller (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 // 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 #include #include #include // 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 #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); }