// JM modified for Ultrasonic and DHT-22 #include #include //JM #include #include #include #include //#include #define SERIAL 0 // set to 1 to also report readings on the serial port #define DEBUG 0 // set to 1 to display each loop() run and PIR trigger #define ECHOPIN 3 // Pin to receive echo pulse #define TRIGPIN 6 // Pin to send trigger pulse #define tank_height 111 //in centimetres #define tank_width 67 //in centimetres #define tank_length 162 //in centimetres #define sensor_offset 8 //in centimetres #define MEASURE_PERIOD 30 // how often to measure, in tenths of seconds #define RETRY_PERIOD 10 // how soon to retry 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 REPORT_EVERY 5 // report every N measurement cycles #define SMOOTH 3 // smoothing factor used for running averages // set the sync mode to 2 if the fuses are still the Arduino default // mode 3 (full powerdown) can only be used with 258 CK startup fuses #define RADIO_SYNC_MODE 2 // The scheduler makes it easy to perform various tasks at various times: enum { MEASURE, REPORT, TASK_END }; static word schedbuf[TASK_END]; Scheduler scheduler (schedbuf, TASK_END); // Other variables used in various places in the code: static byte reportCount; // count up until next report, i.e. packet send static byte myNodeID; // node ID used for this unit // This defines the structure of the packets which get sent out by wireless: struct { //byte oil; // percentage full 0 to 100 int oil:16; // oil sensor: 0..32767 byte moved : 1; // motion detector: 0..1 byte humi : 7; // humidity: 0..100 int temp : 10; // temperature: -500..+500 (tenths) byte lobat : 1; // supply voltage dropped under 3.1V: 0..1 } payload; // Conditional code, depending on which sensors are connected and how: // Setup a DHT22 instance DHT22 myDHT22(7); // Setup the DHT pin 7// JM // has to be defined because we're using the watchdog for low-power waiting ISR(WDT_vect) { Sleepy::watchdogEvent(); } // spend a little time in power down mode while the SHT11 does a measurement static void shtDelay () { Sleepy::loseSomeTime(32); // must wait at least 20 ms } // wait a few milliseconds for proper ACK to me, return true if indeed received static byte waitForAck() { MilliTimer ackTimer; while (!ackTimer.poll(ACK_TIME)) { if (rf12_recvDone() && rf12_crc == 0 && // see http://talk.jeelabs.net/topic/811#post-4712 rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID)) return 1; set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); } return 0; } // readout all the sensors and other values static void doMeasure() { // Do ultrasonic measurement digitalWrite(TRIGPIN, LOW); delayMicroseconds(2); digitalWrite(TRIGPIN, HIGH); delayMicroseconds(10); digitalWrite(TRIGPIN, LOW); // Compute distance float distance = pulseIn(ECHOPIN, HIGH); distance= (distance/58)-sensor_offset; float litres=((tank_height-distance)*tank_length*tank_width)/1000; payload.oil=litres; delay(200); //byte firstTime = payload.humi == 0; // special case to init running avg payload.lobat = rf12_lowbat(); DHT22_ERROR_t errorCode; errorCode = myDHT22.readData(); payload.humi=(myDHT22.getHumidity()); payload.temp=(myDHT22.getTemperatureC())*10; } // periodic report, i.e. send out a packet and optionally report on serial port static void doReport() { // the RF12 runs on INT0 this interrupt is on PCINT18 the same as port PD as // the PIR (PCINT23) so when the RF12 is being used the entire PORT gets a PIN // CHANGE event PCIFR. // We need to capture this and mask it off so the PIR does not fire again. PCICR &= ~(1 << PCIE2); // disable the PD pin-change interrupt. rf12_sleep(RF12_WAKEUP); while (!rf12_canSend()) rf12_recvDone(); rf12_sendStart(0, &payload, sizeof payload, RADIO_SYNC_MODE); rf12_sleep(RF12_SLEEP); // When a logic change on any PCINT23:16 pin triggers an interrupt request, // PCIF2 becomes set(one). If the I-bit in SREG and the PCIE2 bit in PCICR // are set (one), the MCU will jump to thecorresponding Interrupt Vector. // The flag is cleared when the interrupt routine is executed. Alternatively, // the flag can be cleared by writing a logical one to it. PCIFR = (1<= REPORT_EVERY) { reportCount = 0; scheduler.timer(REPORT, 0); } break; case REPORT: doReport(); break; } }