//---------------------------------------------------------------------------------------------------------------------- // TinyTX - An ATtiny84 and RFM12B Wireless Temperature & Humidity Sensor Node // By Nathan Chantrell. For hardware design see http://nathan.chantrell.net/tinytx // // Using the DHT22 temperature and humidity sensor // // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence: // http://creativecommons.org/licenses/by-sa/3.0/ // // Requires Arduino IDE with arduino-tiny core: http://code.google.com/p/arduino-tiny/ // // From Page: https://raspberry.tips/raspberrypi-tutorials/diy-temperatur-und-leuftfeuchte-sensoren-mit-rfm69cw-funksender/ //---------------------------------------------------------------------------------------------------------------------- #define RF69_COMPAT 1 #include // https://github.com/nathanchantrell/Arduino-DHT22 #include // https://github.com/jcw/jeelib ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving //#define myNodeID 16 // BAD -> RF12 node ID in the range 1-30 //#define myNodeID 17 // Kueche -> RF12 node ID in the range 1-30 //#define myNodeID 18 // Schalfzimmer -> RF12 node ID in the range 1-30 //#define myNodeID 19 // Wohnzimmer -> RF12 node ID in the range 1-30 -> mit ACK #define myNodeID 20 // Outdoor -> RF12 node ID in the range 1-30 -> mit ACK #define network 210 // RF12 Network group #define freq RF12_433MHZ // Frequency of RFM12B module #define SLEEPTIME 5 // min to sleep #define USE_ACK // Enable ACKs, comment out to disable #define RETRY_PERIOD 5 // How soon to retry (in seconds) if ACK didn't come in #define RETRY_LIMIT 5 // Maximum number of times to retry #define ACK_TIME 10 // Number of milliseconds to wait for an ack #define DHT22_PIN 10 // DHT sensor is connected on D10/ATtiny pin 13 #define DHT22_POWER 9 // DHT Power pin is connected on D9/ATtiny pin 12 #define STATUS_SENDDATA 0 #define STATUS_INIT 1 #define STATUS_ERROR_DHT 2 #define STATUS_ERROR_VCC 3 DHT22 myDHT22(DHT22_PIN); // Setup the DHT //######################################################################################################################## //Data Structure to be sent //######################################################################################################################## typedef struct { int humidity; // Humidity reading int supplyV; // Supply voltage int temp; // Temperature reading } Payload; Payload tinytx; // Wait a few milliseconds for proper ACK #ifdef USE_ACK static byte waitForAck() { MilliTimer ackTimer; while (!ackTimer.poll(ACK_TIME)) { if (rf12_recvDone() && rf12_crc == 0 && rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID)) return 1; } return 0; } #endif //-------------------------------------------------------------------------------------------------- // Send payload data via RF //------------------------------------------------------------------------------------------------- static void rfwrite(int status) { if (status != STATUS_SENDDATA) { tinytx.humidity = 0; tinytx.supplyV = 0; tinytx.temp = status; } #ifdef USE_ACK for (byte i = 0; i <= RETRY_LIMIT; ++i) { // tx and wait for ack up to RETRY_LIMIT times rf12_sleep(-1);// Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(RF12_HDR_ACK, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode byte acked = waitForAck(); // Wait for ACK rf12_sleep(0); // Put RF module to sleep if (acked) { return; } // Return if ACK received Sleepy::loseSomeTime(RETRY_PERIOD * 1000); // If no ack received wait and try again } #else rf12_sleep(-1); // Wake up RF module while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, &tinytx, sizeof tinytx); rf12_sendWait(2); // Wait for RF to finish sending while in standby mode rf12_sleep(0); // Put RF module to sleep return; #endif } //-------------------------------------------------------------------------------------------------- // Read current supply voltage //-------------------------------------------------------------------------------------------------- long readVcc() { bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC long result; // Read 1.1V reference against Vcc #if defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84 #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // For ATmega328 #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert // ge�ndert !! //int timeoutCounter = 1000; //while ((bit_is_set(ADCSRA, ADSC)) && (timeoutCounter > 0)) timeoutCounter--; while (bit_is_set(ADCSRA, ADSC)); result = ADCL; result |= ADCH << 8; result = 1126400L / result; // Back-calculate Vcc in mV ADCSRA &= ~bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power //if (timeoutCounter == 0) result = 0; return result; } //######################################################################################################################## void setup() { rf12_initialize(myNodeID, freq, network); // Initialize RFM12 with settings defined above rf12_sleep(0); // Put the RFM12 to sleep pinMode(DHT22_POWER, OUTPUT); // set power pin for DHT to output PRR = bit(PRTIM1); // only keep timer 0 going ADCSRA &= ~bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power //rfwrite(STATUS_INIT); // Send Status INIT via RF } void loop() { digitalWrite(DHT22_POWER, HIGH); // turn DHT sensor on DHT22_ERROR_t errorCode; Sleepy::loseSomeTime(3000); // Sensor requires minimum 2s warm-up after power-on. errorCode = myDHT22.readData(); // read data from sensor if (errorCode == DHT_ERROR_NONE) { // data is good tinytx.temp = (myDHT22.getTemperatureC() * 100); // Get temperature reading and convert to integer, reversed at receiving end tinytx.humidity = (myDHT22.getHumidity() * 100); // Get humidity reading and convert to integer, reversed at receiving end tinytx.supplyV = readVcc(); // Get supply voltage rfwrite(STATUS_SENDDATA); // Send data via RF } else { rfwrite(STATUS_ERROR_DHT); // Send ERROR Code via RF } digitalWrite(DHT22_POWER, LOW); // turn DS18B20 off // Sleep for some Minutes for (int i = 0; i < SLEEPTIME; i++) { Sleepy::loseSomeTime(60000); //JeeLabs power save function: enter low power mode for 60 seconds (valid range 16-65000 ms) } }