├── Field_Node_Garage.ino ├── Field_Node_Mailbox.ino ├── Gateway_Ethernet.ino ├── Gateway_RFM.ino ├── OpenHAB_Config.txt ├── README.md ├── UberSensor.ino ├── UberSensor_OpenHAB_Config.txt ├── battery_powered_arduino_frizing.jpg ├── battery_powered_arduino_jpg.jpg ├── dog_tracker.ino ├── dog_tracker_gateway ├── laundry_room.config └── laundry_room.ino /Field_Node_Garage.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 7-21-2014 5 | File: Mailbox.ino 6 | This sleeps until interrupted, then sends data via RFM69 7 | 8 | Modifications Needed: 9 | 1) Update encryption string "ENCRYPTKEY" 10 | 2) 11 | */ 12 | 13 | 14 | //RFM69 -------------------------------------------------------------------------------------------------- 15 | #include 16 | #include 17 | #define NODEID 40 //unique for each node on same network 18 | #define NETWORKID 10 //the same on all nodes that talk to each other 19 | #define GATEWAYID 1 20 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 21 | //#define FREQUENCY RF69_433MHZ 22 | //#define FREQUENCY RF69_868MHZ 23 | #define FREQUENCY RF69_915MHZ 24 | #define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //exactly the same 16 characters/bytes on all nodes! 25 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 26 | #define ACK_TIME 30 // max # of ms to wait for an ack 27 | #define LED 9 // Moteinos have LEDs on D9 28 | #define SERIAL_BAUD 9600 //must be 9600 for GPS, use whatever if no GPS 29 | //deviceID's 30 | // 2 = light sensor 31 | // 3 = ultrasonic 32 | // 4 = temperature_F/humidity 33 | // 5 = presence sensor PIR 34 | 35 | typedef struct { 36 | int nodeID; //node ID (1xx, 2xx, 3xx); 1xx = basement, 2xx = main floor, 3xx = outside 37 | int deviceID; //sensor ID (2, 3, 4, 5) 38 | unsigned long var1_usl; //uptime in ms 39 | float var2_float; //sensor data? 40 | float var3_float; //battery condition? 41 | } Payload; 42 | Payload theData; 43 | 44 | char buff[20]; 45 | byte sendSize=0; 46 | boolean requestACK = false; 47 | RFM69 radio; 48 | 49 | //end RFM69 ------------------------------------------ 50 | 51 | 52 | 53 | //device DHT11 Temperature/Humidity 54 | #include 55 | #define DHTPIN 4 // what pin we're connected to 56 | #define DHTTYPE DHT11 // DHT 11 57 | DHT dht(DHTPIN, DHTTYPE); 58 | 59 | 60 | //device light sensor 61 | int lightPin = 0; //define an analog pin for Photo resistor 62 | 63 | 64 | //device ultrasonic 65 | const int pingPin = 3; 66 | const int trigPin = 5; 67 | 68 | //device PIR 69 | const int PIRpin = 6; 70 | 71 | //round robbin 72 | int dev2_trans_period = 7000; 73 | long dev2_last_period = -1; 74 | int dev3_trans_period = 5000; 75 | long dev3_last_period = -1; 76 | int dev4_trans_period = 9000; 77 | long dev4_last_period = -1; 78 | int dev5_trans_period = 11000; 79 | long dev5_last_period = -1; 80 | 81 | 82 | 83 | 84 | //time: 85 | // 2 = light sensor 86 | const unsigned long dev2_period = 600000; //send data every X seconds 87 | const unsigned long dev2_change = 20000; //examine for change every X seconds 88 | unsigned long dev2_period_time; //seconds since last period 89 | unsigned long dev2_change_time; //seconds since last examination 90 | const int dev2_change_amt = 100; //change amount to notify of change 91 | int dev2_current_value = -200; //light sensor current value 92 | 93 | // 3 = ultrasonic 94 | const unsigned long dev3_period = 700000; //700000 //send data every X seconds 95 | const unsigned long dev3_change = 15000; //examine for change every X seconds 96 | unsigned long dev3_period_time; //seconds since last period 97 | unsigned long dev3_change_time; //seconds since last examination 98 | const int dev3_change_amt = 12; //change amount to notify of change 99 | int dev3_current_value = -200; //light sensor current value 100 | 101 | // 3 = temperature 102 | const unsigned long dev4_period = 710000; //700000 //send data every X seconds 103 | unsigned long dev4_period_time; //seconds since last period 104 | 105 | 106 | 107 | 108 | // 4 = temperature_F/humidity 109 | // 5 = presence sensor PIR 110 | 111 | 112 | 113 | void setup() 114 | { 115 | Serial.begin(SERIAL_BAUD); //Begin serial communcation 116 | 117 | //RFM69------------------------------------------- 118 | 119 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 120 | #ifdef IS_RFM69HW 121 | radio.setHighPower(); //uncomment only for RFM69HW! 122 | #endif 123 | radio.encrypt(ENCRYPTKEY); 124 | char buff[50]; 125 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 126 | Serial.println(buff); 127 | theData.nodeID = 40; //this node id should be the same for all devices in this node 128 | 129 | //-------------------------------------- 130 | //light sensor 131 | int lightOutput; 132 | 133 | 134 | //device ultrasonic 135 | pinMode(pingPin, INPUT); 136 | pinMode(trigPin, OUTPUT); 137 | 138 | //device DHT 139 | dht.begin(); 140 | 141 | //device PIR 142 | pinMode(PIRpin, INPUT); 143 | 144 | //time: 145 | //dev2 is light 146 | dev2_period_time = millis(); //seconds since last period 147 | dev2_change_time = millis(); //seconds since last examination 148 | //dev2 is ultrasonic 149 | dev3_period_time = millis(); //seconds since last period 150 | dev3_change_time = millis(); //seconds since last examination 151 | 152 | 153 | // dev4 is temperature_F/humidity 154 | dev4_period_time = millis(); //seconds since last period 155 | 156 | // 5 = presence sensor PIR 157 | 158 | } 159 | //--------------------------------------------------------------------------------------------- 160 | 161 | 162 | //--------------------------------------------------------------------------------------------- 163 | void loop() 164 | { 165 | 166 | //---- this is what data looks like ----- 167 | /* 168 | theData.nodeID = 40; 169 | theData.sensorID = xx; 170 | 2 = lights sensor var1 = 0-1024, higher means more light 171 | 3 = ultrasonic var1 = inches 172 | 4 = temperature_F/humidity var1= degree F, var2=% humidity 173 | 5 = presence sensor var: = 1 = presence, 0=absence 174 | theData.var1_usl = millis(); 175 | theData.var2_float = ; 176 | theData.var3_float = ; 177 | */ 178 | 179 | 180 | 181 | 182 | //---------------- start devices ------------------------------------------------ 183 | 184 | 185 | delay(2000); //short delay for faster response to light. 186 | 187 | 188 | //------------------------------------------------------------------------------- 189 | // deviceID = 2; //light sensor 190 | //------------------------------------------------------------------------------- 191 | //light sensor--------------------- 192 | int lightOutput; 193 | 194 | //always report after X seconds 195 | unsigned long timepassed = millis() - dev2_period_time; 196 | 197 | /* 198 | Serial.print(" timepassed = "); 199 | Serial.print(timepassed); 200 | Serial.print(" dev2_period(60sec) = "); 201 | Serial.print(dev2_period); 202 | Serial.print(" millis = "); 203 | Serial.print(millis()); 204 | Serial.print(" dev2_period_time = "); 205 | Serial.println(dev2_period_time); 206 | */ 207 | if ((timepassed > dev2_period) || (timepassed < 0)) 208 | { 209 | Serial.println("doing the long one!!!"); 210 | Serial.print(" timepassed = "); 211 | Serial.print(timepassed); 212 | Serial.print(" dev2_period(60sec) = "); 213 | Serial.print(dev2_period); 214 | Serial.print(" millis = "); 215 | Serial.print(millis()); 216 | Serial.print(" dev2_period_time = "); 217 | Serial.println(dev2_period_time); 218 | lightOutput = analogRead(lightPin); 219 | 220 | //send data 221 | theData.deviceID = 2; 222 | theData.var1_usl = millis(); 223 | theData.var2_float = lightOutput; 224 | theData.var3_float = 0; 225 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 226 | 227 | //reset timer 228 | dev2_period_time = millis(); 229 | dev2_change_time = millis(); //count this sensor examination 230 | } 231 | 232 | //examine for change every change_time seconds; 233 | timepassed = millis() - dev2_change_time; 234 | if ((timepassed > dev2_change) || (timepassed < 0)) 235 | { 236 | Serial.println("doing the shooooor!"); 237 | lightOutput = analogRead(lightPin); 238 | 239 | if ((lightOutput > (dev2_current_value + dev2_change_amt)) || (lightOutput < (dev2_current_value - dev2_change_amt))) 240 | { 241 | Serial.println("change detected"); 242 | dev2_current_value = lightOutput; 243 | //send data 244 | theData.deviceID = 2; 245 | theData.var1_usl = millis(); 246 | theData.var2_float = lightOutput; 247 | theData.var3_float = 0; 248 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 249 | } 250 | dev2_change_time = millis(); 251 | } 252 | 253 | delay(200); 254 | 255 | //------------------------------------------------------------------------------- 256 | // deviceID = 3; ultrasonic 257 | //------------------------------------------------------------------------------- 258 | unsigned long duration; 259 | float inches, cm; 260 | 261 | //send every x seconds 262 | timepassed = millis() - dev3_period_time; 263 | if ((timepassed > dev3_period) || (timepassed < 0)) 264 | { 265 | Serial.println("doing the long one dev 3!!!"); 266 | Serial.print(" timepassed = "); 267 | Serial.print(timepassed); 268 | Serial.print(" dev3_period(60sec) = "); 269 | Serial.print(dev3_period); 270 | Serial.print(" millis = "); 271 | Serial.print(millis()); 272 | Serial.print(" dev3_period_time = "); 273 | Serial.println(dev3_period_time); 274 | 275 | 276 | //get data 277 | digitalWrite(trigPin, LOW); 278 | delayMicroseconds(2); 279 | digitalWrite(trigPin, HIGH); 280 | delayMicroseconds(15); 281 | digitalWrite(trigPin, LOW); 282 | duration = pulseIn(pingPin, HIGH); 283 | // convert the time into a distance 284 | inches = microsecondsToInches(duration); 285 | Serial.print(inches); 286 | Serial.println(" inches"); 287 | //send data 288 | theData.deviceID = 3; 289 | theData.var1_usl = millis(); 290 | theData.var2_float = inches; 291 | theData.var3_float = 0; 292 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 293 | 294 | //reset timer 295 | dev3_period_time = millis(); 296 | dev3_change_time = millis(); //count this sensor examination 297 | } 298 | 299 | //examine for change every change_time seconds; 300 | timepassed = millis() - dev3_change_time; 301 | if ((timepassed > dev3_change) || (timepassed < 0)) 302 | { 303 | Serial.println("doing the shooooor!"); 304 | 305 | //get data 306 | digitalWrite(trigPin, LOW); 307 | delayMicroseconds(2); 308 | digitalWrite(trigPin, HIGH); 309 | delayMicroseconds(15); 310 | digitalWrite(trigPin, LOW); 311 | duration = pulseIn(pingPin, HIGH); 312 | // convert the time into a distance 313 | inches = microsecondsToInches(duration); 314 | Serial.print(inches); 315 | Serial.println(" inches"); 316 | 317 | 318 | if ((inches > (dev3_current_value + dev3_change_amt)) || (inches < (dev3_current_value - dev3_change_amt))) 319 | { 320 | Serial.println("change detected"); 321 | dev3_current_value = inches; 322 | //send data 323 | theData.deviceID = 3; 324 | theData.var1_usl = millis(); 325 | theData.var2_float = inches; 326 | theData.var3_float = 0; 327 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 328 | } 329 | dev2_change_time = millis(); 330 | } 331 | 332 | 333 | delay(200); 334 | 335 | //------------------------------------------------------------------------------- 336 | // deviceID = 4; //temperature humidity 337 | //------------------------------------------------------------------------------- 338 | //DHT11 -------------------------------- 339 | float h = dht.readHumidity(); 340 | float t = dht.readTemperature(); 341 | float temp_F; 342 | //send every x seconds 343 | timepassed = millis() - dev4_period_time; 344 | if ((timepassed > dev4_period) || (timepassed < 0)) 345 | { 346 | if (isnan(t) || isnan(h)) { 347 | Serial.println("Failed to read from DHT"); 348 | } else { 349 | Serial.print("Humidity: "); 350 | Serial.print(h); 351 | Serial.print(" %\t"); 352 | Serial.print("Temperature: "); 353 | Serial.print(t); 354 | Serial.print(" *C\t"); 355 | temp_F = t * 9/5+32; 356 | Serial.print(temp_F); 357 | Serial.println(" *F"); 358 | } 359 | //send data 360 | theData.deviceID = 4; 361 | theData.var1_usl = millis(); 362 | theData.var2_float = temp_F; 363 | theData.var3_float = h; 364 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 365 | 366 | dev4_period_time = millis(); 367 | } 368 | 369 | }//end loop 370 | 371 | //--------------------------------------------------------------------------------------------- 372 | //--------------------------------------------------------------------------------------------- 373 | float microsecondsToInches(long microseconds) 374 | { 375 | // According to Parallax's datasheet for the PING))), there are 376 | // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per 377 | // second). This gives the distance travelled by the ping, outbound 378 | // and return, so we divide by 2 to get the distance of the obstacle. 379 | // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf 380 | return microseconds / 74.0 / 2.0; 381 | } 382 | //--------------------------------------------------------------------------------------------- 383 | //--------------------------------------------------------------------------------------------- 384 | float microsecondsToCentimeters(long microseconds) 385 | { 386 | // The speed of sound is 340 m/s or 29 microseconds per centimeter. 387 | // The ping travels out and back, so to find the distance of the 388 | // object we take half of the distance travelled. 389 | return microseconds / 29 / 2; 390 | } 391 | -------------------------------------------------------------------------------- /Field_Node_Mailbox.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 7-21-2014 5 | File: Mailbox.ino 6 | This sleeps until interrupted, then sends data via RFM69 7 | 8 | Modifications Needed: 9 | 1) Update encryption string "ENCRYPTKEY" 10 | 2) 11 | */ 12 | 13 | //RFM69 -------------------------------------------------------------------------------------------------- 14 | #include 15 | #include 16 | #define NODEID 41 //unique for each node on same network 17 | #define NETWORKID 101 //the same on all nodes that talk to each other 18 | #define GATEWAYID 1 19 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 20 | //#define FREQUENCY RF69_433MHZ 21 | //#define FREQUENCY RF69_868MHZ 22 | #define FREQUENCY RF69_915MHZ 23 | #define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes! 24 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 25 | #define ACK_TIME 30 // max # of ms to wait for an ack 26 | 27 | #define SERIAL_BAUD 9600 //must be 9600 for GPS, use whatever if no GPS 28 | //deviceID's 29 | 30 | typedef struct { 31 | int nodeID; 32 | int deviceID; 33 | unsigned long var1_usl; 34 | float var2_float; 35 | float var3_float; 36 | } Payload; 37 | Payload theData; 38 | 39 | char buff[20]; 40 | byte sendSize=0; 41 | boolean requestACK = false; 42 | RFM69 radio; 43 | 44 | //end RFM69 ------------------------------------------ 45 | 46 | 47 | //analog read 48 | int analogPin = 0; 49 | byte adcsra_save; 50 | 51 | //------------------------- 52 | #include 53 | 54 | const byte LED = 8; 55 | int scan_num = 0; //keep track of how many times opened. 56 | void wake () 57 | { 58 | // must do this as the pin will probably stay low for a while 59 | detachInterrupt (1); 60 | // cancel sleep as a precaution 61 | sleep_disable(); 62 | 63 | } // end of wake 64 | 65 | void setup () 66 | { 67 | digitalWrite (2, HIGH); // enable pull-up 68 | Serial.begin(SERIAL_BAUD); //Begin serial communcation 69 | 70 | adcsra_save = ADCSRA; //save ADCSRA to re-enable later. 71 | 72 | Serial.println("starting"); 73 | //RFM69------------------------------------------- 74 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 75 | #ifdef IS_RFM69HW 76 | radio.setHighPower(); //uncomment only for RFM69HW! 77 | #endif 78 | radio.encrypt(ENCRYPTKEY); 79 | char buff[50]; 80 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 81 | Serial.println(buff); 82 | theData.nodeID = 41; //this node id should be the same for all devices in this node 83 | pinMode (LED, OUTPUT); 84 | Serial.println("finished setup"); 85 | } // end of setup 86 | 87 | void loop () 88 | { 89 | 90 | 91 | digitalWrite (LED, HIGH); 92 | 93 | //re-enable analog: 94 | ADCSRA = adcsra_save; 95 | 96 | scan_num = scan_num + 1; 97 | //send data 98 | theData.nodeID = 41; 99 | theData.deviceID = 2; 100 | theData.var1_usl = millis(); 101 | theData.var2_float = scan_num; 102 | 103 | //radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 104 | delay(500); 105 | theData.var3_float = (analogRead(A3))*3.30/1023.00*2.00; 106 | 107 | //use either send; sendwithretry sends it 3 times if no ack 108 | //radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 109 | radio.send(GATEWAYID, (const void*)(&theData), sizeof(theData)); 110 | 111 | digitalWrite (LED, LOW); 112 | 113 | radio.sleep(); 114 | // disable ADC 115 | ADCSRA = 0; 116 | 117 | set_sleep_mode (SLEEP_MODE_PWR_DOWN); 118 | sleep_enable(); 119 | 120 | // Do not interrupt before we go to sleep, or the 121 | // ISR will detach interrupts and we won't wake. 122 | noInterrupts (); 123 | 124 | // will be called when pin D2 goes HIGH 125 | attachInterrupt (1, wake, HIGH); 126 | 127 | // turn off brown-out enable in software 128 | // BODS must be set to one and BODSE must be set to zero within four clock cycles 129 | MCUCR = bit (BODS) | bit (BODSE); 130 | // The BODS bit is automatically cleared after three clock cycles 131 | MCUCR = bit (BODS); 132 | 133 | // We are guaranteed that the sleep_cpu call will be done 134 | // as the processor executes the next instruction after 135 | // interrupts are turned on. 136 | interrupts (); // one cycle 137 | sleep_cpu (); // one cycle 138 | 139 | } // end of loop 140 | -------------------------------------------------------------------------------- /Gateway_Ethernet.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 7-21-2014 5 | File: Ethernet_Gateway.ino 6 | This sketch takes data struct from I2C and publishes it to 7 | mosquitto broker. 8 | 9 | Modifications Needed: 10 | 1) Update mac address "mac[]" 11 | 2) Update MQTT broker IP address "server[]" 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | //I2C receive device address 20 | const byte MY_ADDRESS = 42; //I2C comms w/ other Arduino 21 | 22 | //Ethernet 23 | byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x11, 0x11 }; 24 | byte server[] = { 192, 168, 1, 51 }; //your MQTT broker IP address 25 | 26 | //IPAddress ip(192,168,2,61); 27 | EthernetClient ethClient; 28 | PubSubClient client(server, 1883, callback, ethClient); 29 | unsigned long keepalivetime=0; 30 | unsigned long MQTT_reconnect=0; 31 | 32 | 33 | //use LED for indicating MQTT connection status. 34 | int led = 13; 35 | bool conn_ok; 36 | 37 | void callback(char* topic, byte* payload, unsigned int length) { 38 | // handle message arrived 39 | } 40 | 41 | 42 | void setup() 43 | { 44 | //ethernet 45 | //Ethernet.begin(mac, ip); 46 | Wire.begin (MY_ADDRESS); 47 | Serial.begin (9600); 48 | 49 | Serial.println("starting"); 50 | 51 | pinMode(led, OUTPUT); 52 | 53 | //wait for IP address 54 | 55 | while (Ethernet.begin(mac) != 1) 56 | 57 | { 58 | Serial.println("Error getting IP address via DHCP, trying again..."); 59 | delay(3000); 60 | } 61 | 62 | //Ethernet.begin(mac, ip); 63 | Serial.println("ethernet OK"); 64 | keepalivetime=millis(); 65 | Wire.onReceive (receiveEvent); 66 | 67 | while (client.connect("arduinoClient") != 1) 68 | { 69 | Serial.println("Error connecting to MQTT"); 70 | delay(3000); 71 | } 72 | MQTT_reconnect = millis(); 73 | Serial.println("setup complete"); 74 | 75 | } // end of setup 76 | 77 | 78 | 79 | volatile struct 80 | { 81 | int nodeID; 82 | int sensorID; 83 | unsigned long var1_usl; 84 | float var2_float; 85 | float var3_float; // 86 | int var4_int; 87 | } SensorNode; 88 | 89 | int sendMQTT = 0; 90 | volatile boolean haveData = false; 91 | 92 | void loop() 93 | { 94 | 95 | //if new data on I2C from RFM gateway received, flag for MQTT publish 96 | if (haveData) 97 | { 98 | Serial.print ("Received Device ID = "); 99 | Serial.println (SensorNode.sensorID); 100 | Serial.print (" Time = "); 101 | Serial.println (SensorNode.var1_usl); 102 | Serial.print (" var2_float "); 103 | Serial.println (SensorNode.var2_float); 104 | 105 | sendMQTT = 1; 106 | 107 | /* 108 | if (client.connect("arduinoClient")) 109 | { 110 | int varnum = 1; 111 | char buff_topic[6]; 112 | char buff_message[6]; 113 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 114 | Serial.println(buff_topic); 115 | dtostrf (SensorNode.var2_float, 4, 1, buff_message); 116 | client.publish(buff_topic, buff_message); 117 | } 118 | */ 119 | 120 | haveData = false; 121 | } // end if haveData 122 | 123 | 124 | if (sendMQTT == 1) 125 | { 126 | 127 | Serial.println("starting MQTT send"); 128 | 129 | //check to make sure connected to MQTT before trying to publish data 130 | conn_ok = client.connected(); 131 | if (conn_ok==1) 132 | { 133 | digitalWrite(led, HIGH); 134 | Serial.println("MQTT connected OK from MQTT Send"); 135 | } 136 | else 137 | { 138 | digitalWrite(led, LOW); 139 | Serial.println("MQTT NOT connected OK from MQTT Send"); 140 | } 141 | 142 | //no connection, reconnect 143 | if (conn_ok == 0) 144 | { 145 | client.disconnect(); 146 | delay(5000); 147 | while (client.connect("arduinoClient") != 1) 148 | { 149 | digitalWrite(led, LOW); 150 | Serial.println("Error connecting to MQTT"); 151 | delay(4000); 152 | digitalWrite(led, HIGH); 153 | } 154 | digitalWrite(led, HIGH); 155 | Serial.println("reconnected to MQTT"); 156 | MQTT_reconnect = millis(); 157 | } 158 | 159 | 160 | int varnum; 161 | char buff_topic[6]; 162 | char buff_message[12]; 163 | 164 | 165 | /* 166 | //send var1_usl 167 | varnum = 2; 168 | buff_topic[6]; 169 | buff_message[12]; 170 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 171 | Serial.println(buff_topic); 172 | dtostrf (SensorNode.var1_usl, 10, 1, buff_message); 173 | client.publish(buff_topic, buff_message); 174 | */ 175 | 176 | //send var2_float 177 | varnum = 2; 178 | buff_topic[6]; 179 | buff_message[7]; 180 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 181 | Serial.println(buff_topic); 182 | dtostrf (SensorNode.var2_float, 2, 1, buff_message); 183 | client.publish(buff_topic, buff_message); 184 | 185 | delay(200); 186 | 187 | //send var3_float 188 | varnum = 3; 189 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 190 | Serial.println(buff_topic); 191 | dtostrf (SensorNode.var3_float, 2, 1, buff_message); 192 | client.publish(buff_topic, buff_message); 193 | 194 | delay(200); 195 | 196 | //send var4_int, RSSI 197 | varnum = 4; 198 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 199 | Serial.println(buff_topic); 200 | sprintf(buff_message, "%04d%", SensorNode.var4_int); 201 | client.publish(buff_topic, buff_message); 202 | 203 | sendMQTT = 0; 204 | Serial.println("finished MQTT send"); 205 | }//end if sendMQTT 206 | 207 | 208 | //client.loop needs to run every iteration. Previous version did not. Big opps. 209 | client.loop(); 210 | 211 | //regularly check MQTT connection (ever x seconds) 212 | if ((millis() - MQTT_reconnect) > 60000) 213 | { 214 | conn_ok = client.connected(); 215 | if (conn_ok==1) 216 | { 217 | digitalWrite(led, HIGH); 218 | Serial.println("MQTT connected OK"); 219 | } 220 | else 221 | { 222 | digitalWrite(led, LOW); 223 | Serial.println("MQTT NOT connected OK"); 224 | } 225 | 226 | //no connection, reconnect 227 | if (conn_ok == 0) 228 | { 229 | client.disconnect(); 230 | delay(5000); 231 | while (client.connect("arduinoClient") != 1) 232 | { 233 | digitalWrite(led, LOW); 234 | Serial.println("Error connecting to MQTT"); 235 | delay(4000); 236 | digitalWrite(led, HIGH); 237 | } 238 | digitalWrite(led, HIGH); 239 | } 240 | 241 | Serial.println("reconnected to MQTT"); 242 | MQTT_reconnect = millis(); 243 | } 244 | 245 | } // end of loop 246 | 247 | 248 | 249 | 250 | // called by interrupt service routine when incoming data arrives 251 | void receiveEvent (int howMany) 252 | { 253 | if (howMany < sizeof SensorNode) 254 | return; 255 | 256 | // read into structure 257 | byte * p = (byte *) &SensorNode; 258 | for (byte i = 0; i < sizeof SensorNode; i++) 259 | *p++ = Wire.read (); 260 | 261 | haveData = true; 262 | } 263 | -------------------------------------------------------------------------------- /Gateway_RFM.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 7-21-2014 5 | File: RFM_Gateway.ino 6 | This sketch receives RFM wireless data and forwards it to I2C 7 | 8 | Modifications Needed: 9 | 1) Update encryption string "ENCRYPTKEY" 10 | 2) 11 | */ 12 | 13 | /* 14 | RFM69 Pinout: 15 | MOSI = 11 16 | MISO = 12 17 | SCK = 13 18 | SS = 10 19 | */ 20 | 21 | 22 | //general -------------------------------- 23 | #define SERIAL_BAUD 9600 24 | 25 | 26 | 27 | //RFM69 ---------------------------------- 28 | #include 29 | #include 30 | #define NODEID 1 //unique for each node on same network 31 | #define NETWORKID 101 //the same on all nodes that talk to each other 32 | #define FREQUENCY RF69_915MHZ 33 | #define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes! 34 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 35 | #define ACK_TIME 30 // max # of ms to wait for an ack 36 | 37 | RFM69 radio; 38 | bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network 39 | //I2C ----------------------------------- 40 | #include 41 | const byte TARGET_ADDRESS = 42; 42 | 43 | typedef struct { 44 | int nodeID; 45 | int sensorID; 46 | unsigned long var1_usl; 47 | float var2_float; 48 | float var3_float; 49 | } Payload; 50 | Payload theData; 51 | 52 | typedef struct { 53 | int nodeID; 54 | int sensorID; 55 | unsigned long var1_usl; 56 | float var2_float; 57 | float var3_float; 58 | int var4_int; 59 | } itoc_Send; 60 | itoc_Send theDataI2C; 61 | 62 | 63 | void setup() 64 | { 65 | Wire.begin (); 66 | 67 | Serial.begin(9600); 68 | 69 | //RFM69 --------------------------- 70 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 71 | #ifdef IS_RFM69HW 72 | radio.setHighPower(); //uncomment only for RFM69HW! 73 | #endif 74 | radio.encrypt(ENCRYPTKEY); 75 | radio.promiscuous(promiscuousMode); 76 | char buff[50]; 77 | sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 78 | Serial.println(buff); 79 | 80 | } // end of setup 81 | 82 | byte ackCount=0; 83 | 84 | 85 | void loop() 86 | { 87 | 88 | if (radio.receiveDone()) 89 | { 90 | //Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 91 | if (promiscuousMode) 92 | { 93 | Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] "); 94 | } 95 | 96 | 97 | if (radio.DATALEN != sizeof(Payload)) 98 | Serial.println("Invalid payload received, not matching Payload struct!"); 99 | else 100 | { 101 | theData = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else 102 | 103 | Serial.print(theData.sensorID); 104 | Serial.print(", "); 105 | Serial.print(theData.var1_usl); 106 | Serial.print(", "); 107 | Serial.print(theData.var2_float); 108 | Serial.print(", "); 109 | //Serial.print(" var2(temperature)="); 110 | //Serial.print(", "); 111 | //Serial.print(theData.var3_float); 112 | 113 | //printFloat(theData.var2_float, 5); Serial.print(", "); printFloat(theData.var3_float, 5); 114 | 115 | Serial.print(", RSSI= "); 116 | Serial.println(radio.RSSI); 117 | 118 | //save it for i2c: 119 | theDataI2C.nodeID = theData.nodeID; 120 | theDataI2C.sensorID = theData.sensorID; 121 | theDataI2C.var1_usl = theData.var1_usl; 122 | theDataI2C.var2_float = theData.var2_float; 123 | theDataI2C.var3_float = theData.var3_float; 124 | theDataI2C.var4_int = radio.RSSI; 125 | } 126 | 127 | 128 | if (radio.ACK_REQUESTED) 129 | { 130 | byte theNodeID = radio.SENDERID; 131 | radio.sendACK(); 132 | //Serial.print(" - ACK sent."); 133 | 134 | // When a node requests an ACK, respond to the ACK 135 | // and also send a packet requesting an ACK (every 3rd one only) 136 | // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY 137 | if (ackCount++%3==0) 138 | { 139 | //Serial.print(" Pinging node "); 140 | //Serial.print(theNodeID); 141 | //Serial.print(" - ACK..."); 142 | //delay(3); //need this when sending right after reception .. ? 143 | //if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0)) // 0 = only 1 attempt, no retries 144 | // Serial.print("ok!"); 145 | //else Serial.print("nothing"); 146 | } 147 | }//end if radio.ACK_REQESTED 148 | 149 | 150 | //send wireless data to I2C 151 | Wire.beginTransmission (TARGET_ADDRESS); 152 | Wire.write ((byte *) &theDataI2C, sizeof theDataI2C); 153 | Wire.endTransmission (); 154 | 155 | 156 | } //end if radio.receive 157 | 158 | }//end loop 159 | -------------------------------------------------------------------------------- /OpenHAB_Config.txt: -------------------------------------------------------------------------------- 1 | 1) Under /configurations/openhab.cfg 2 | 3 | 4 | ######################## Mail Action configuration ############################$ 5 | 6 | mail:hostname=smtp.gmail.com 7 | 8 | mail:port=587 9 | 10 | mail:username=????? without the @gmail 11 | mail:password=????? 12 | 13 | mail:from=??? yourname@gmail.com 14 | 15 | mail:tls=true 16 | 17 | 18 | 19 | 20 | 21 | ################################### MQTT Transport ######################################### 22 | # 23 | 24 | mqtt:mymosquitto.url=tcp://localhost:1883 25 | 26 | mqtt:mymosquitto.qos=0 27 | 28 | mqtt:mymosquitto.retain=true 29 | 30 | mqtt:mymosquitto.async=true 31 | 32 | 33 | ----------------------------------------------------------------------------------------- 34 | 35 | 2) Under /configurations/items/demo.items 36 | 37 | 38 | Switch itm_mailbox "Switch" (ALL) 39 | Number itm_mailboxmqtt "Mailbox RSSI [%.1f]" (ALL) {mqtt="<[mymosquitto:4124:state:default]"} 40 | Number itm_mailboxcnt "Mail Count [%.1f]" (ALL) {mqtt="<[mymosquitto:4122:state:default]"} 41 | DateTime itm_mailbox_time "Mailbox Last Updated [%1$tA, %1$tm/%1$td, %1$tI:%1$tM %1$tp]" 42 | Number itm_mailboxbat "Mailbox Battery [%.1f Volt]" (ALL) {mqtt="<[mymosquitto:4123:state:default]"} 43 | 44 | 45 | 46 | 47 | ----------------------------------------------------------------------------------- 48 | 3) Under /configurations/sitemap/demo.sitemap 49 | 50 | Frame label="Mailbox" 51 | { 52 | Switch item=itm_mailbox label="Mailbox" mappings=[OFF="Off"] 53 | Text item=itm_mailbox_time 54 | Text item=itm_mailboxmqtt 55 | Text item=itm_mailboxcnt 56 | Text item=itm_mailboxbat 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- 61 | 4) Under /configurations/rules/demo.rules 62 | 63 | rule "send email and talk" 64 | when 65 | Item itm_mailbox changed from OFF to ON 66 | then 67 | playSound("aolmail.mp3") 68 | sendMail("myemailaddress@gmail.com", "subject line here" , "email body text") 69 | 70 | 71 | end 72 | 73 | 74 | rule "update mailbox" 75 | when 76 | Item itm_mailboxmqtt received update 77 | then 78 | sendCommand(itm_mailbox, ON) 79 | postUpdate(itm_mailbox_time, new DateTimeType()) 80 | end 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------------- 86 | END OF CONFIGURATIONS 87 | 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OpenHab-RFM69 2 | ============= 3 | 4 | A RFM69-to-MQTT gateway for sensor nodes. Examples of wireless sensor node integration with OpenHAB. 5 | 6 | I'll put up some youtube videos and better explainations later. Hopefully, you got here from one of those youtube videos or my project blog. 7 | 8 | http://www.instructables.com/id/Uber-Home-Automation/ 9 | 10 | ![alt tag](http://cdn.instructables.com/FP4/3HPR/I1SN6AS7/FP43HPRI1SN6AS7.LARGE.jpg) 11 | -------------------------------------------------------------------------------- /UberSensor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 9-1-2014 5 | File: UberSensor.ino 6 | This sketch is for a wired Arduino w/ RFM69 wireless transceiver 7 | Sends sensor data (gas/smoke, flame, PIR, noise, temp/humidity) back 8 | to gateway. See OpenHAB configuration file. 9 | 1) Update encryption string "ENCRYPTKEY" 10 | 2) 11 | */ 12 | 13 | 14 | /* sensor 15 | node = 12 16 | device ID 17 | 2 = 1222 = smoke or not 18 | 3 = 1232 = flame detected or not 19 | 4 = 1242 = human motion present or not 20 | 5 = 1252 = barking or not 21 | 6 = 1262, 1263 = temperature, humidity 22 | 23 | */ 24 | 25 | 26 | 27 | 28 | //RFM69 -------------------------------------------------------------------------------------------------- 29 | #include 30 | #include 31 | #define NODEID 12 //unique for each node on same network 32 | #define NETWORKID 101 //the same on all nodes that talk to each other 33 | #define GATEWAYID 1 34 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 35 | //#define FREQUENCY RF69_433MHZ 36 | //#define FREQUENCY RF69_868MHZ 37 | #define FREQUENCY RF69_915MHZ 38 | #define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes! 39 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 40 | #define ACK_TIME 30 // max # of ms to wait for an ack 41 | #define LED 9 // Moteinos have LEDs on D9 42 | #define SERIAL_BAUD 9600 //must be 9600 for GPS, use whatever if no GPS 43 | 44 | boolean debug = 0; 45 | 46 | //struct for wireless data transmission 47 | typedef struct { 48 | int nodeID; //node ID (1xx, 2xx, 3xx); 1xx = basement, 2xx = main floor, 3xx = outside 49 | int deviceID; //sensor ID (2, 3, 4, 5) 50 | unsigned long var1_usl; //uptime in ms 51 | float var2_float; //sensor data? 52 | float var3_float; //battery condition? 53 | } Payload; 54 | Payload theData; 55 | 56 | char buff[20]; 57 | byte sendSize=0; 58 | boolean requestACK = false; 59 | RFM69 radio; 60 | 61 | //end RFM69 ------------------------------------------ 62 | 63 | 64 | // gas sensor================================================ 65 | int GasSmokeAnalogPin = 0; // potentiometer wiper (middle terminal) connected to analog pin 66 | int gas_sensor = -500; // gas sensor value, current 67 | int gas_sensor_previous = -500; //sensor value previously sent via RFM 68 | 69 | //temperature / humidity ===================================== 70 | #include "DHT.h" 71 | #define DHTPIN 7 // digital pin we're connected to 72 | #define DHTTYPE DHT11 // DHT 22 (AM2302) blue one 73 | //#define DHTTYPE DHT21 // DHT 21 (AM2301) white one 74 | // Initialize DHT sensor for normal 16mhz Arduino 75 | DHT dht(DHTPIN, DHTTYPE); 76 | 77 | // flame sensor ============================================== 78 | int flameAnalogInput = A1; 79 | int flame_status = 0; 80 | int flameValue = -50; //analog value of current flame sensor 81 | int flameValue_previous = -50; //value previously sent via RFM 82 | 83 | // Light sensor =============================================== 84 | int lightAnalogInput = A2; //analog input for photo resistor 85 | int lightValue = -50; 86 | int lightValue_previous = -50; 87 | 88 | // PIR sensor ================================================ 89 | int PirInput = 5; 90 | int PIR_status = 0; 91 | int PIR_reading = 0; 92 | int PIR_reading_previous = 0; 93 | 94 | 95 | // sound sensor ============================================== 96 | //sound sensor digital input pin 97 | int soundInput = 6; 98 | int sound_status = 0; 99 | int sound_reading = 0; //reading =1 mean no noise, 0=noise 100 | int sound_reading_previous = 0; 101 | 102 | // 2 = 1222 = smoke or not 103 | // 3 = 1232 = flame detected or not 104 | // 4 = 1242 = human motion present or not 105 | // 5 = 1252 = barking or not 106 | // 6 = 1262, 1263 = temperature, humidity 107 | 108 | 109 | // timings 110 | unsigned long gas_time; //sensor read time 111 | unsigned long gas_time_send; //sensor value transmission time 112 | unsigned long flame_time; 113 | unsigned long flame_time_send; 114 | unsigned long pir_time; 115 | //unsigned long pir_time_send; 116 | unsigned long sound_time; 117 | //unsigned long sound_time_Send; 118 | unsigned long temperature_time; 119 | unsigned long light_time; 120 | unsigned long light_time_send; 121 | 122 | 123 | void setup() 124 | { 125 | Serial.begin(9600); // setup serial 126 | 127 | //RFM69------------------------------------------- 128 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 129 | #ifdef IS_RFM69HW 130 | radio.setHighPower(); //uncomment only for RFM69HW! 131 | #endif 132 | radio.encrypt(ENCRYPTKEY); 133 | char buff[50]; 134 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 135 | Serial.println(buff); 136 | theData.nodeID = NODEID; //this node id should be the same for all devices in this node 137 | //end RFM-------------------------------------------- 138 | 139 | 140 | //temperature / humidity sensor 141 | dht.begin(); 142 | 143 | //sound/noise 144 | pinMode(soundInput, INPUT); 145 | 146 | 147 | //initialize times 148 | gas_time = millis(); 149 | flame_time = millis(); 150 | pir_time = millis(); 151 | sound_time = millis(); 152 | temperature_time = millis(); 153 | 154 | //PIR sensor 155 | pinMode(PirInput, INPUT); 156 | } 157 | 158 | void loop() 159 | { 160 | 161 | unsigned long time_passed = 0; 162 | 163 | //=================================================================== 164 | //device #2 165 | //read gas sensor 166 | // don't read analog pins too often (<1Hz), else caps never get to charge. 167 | //112 to 120 = normal, 400 = high 168 | 169 | time_passed = millis() - gas_time; 170 | //take care of millis roll over. In case of roll over 171 | //if roll over, send next value again 172 | if (time_passed < 0) 173 | { 174 | gas_time = millis(); 175 | gas_time_send = -700000; 176 | } 177 | 178 | //Serial.print("gas time passed = "); 179 | //Serial.println(time_passed); 180 | if (time_passed > 5000) //read gas sensor analog input every X seconds 181 | { 182 | gas_time = millis(); //update gas_time w/ when sensor last read 183 | gas_sensor = analogRead(GasSmokeAnalogPin); // read the input pin 184 | if (debug){ 185 | Serial.print("Gas = "); 186 | Serial.println(gas_sensor); 187 | } 188 | 189 | //send data if gas detected, or if big changes relative to value last sent, or if it's been a while 190 | if ((gas_sensor < (gas_sensor_previous - 70)) || ((gas_sensor > (gas_sensor_previous + 70)) || (700000 < (millis() - gas_time_send)))) 191 | { 192 | gas_time_send = millis(); //update gas_time_send with when sensor value last transmitted 193 | 194 | theData.deviceID = 2; 195 | theData.var1_usl = millis(); 196 | theData.var2_float = gas_sensor; 197 | theData.var3_float = gas_sensor + 100; //null value; 198 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 199 | gas_sensor_previous = gas_sensor; 200 | Serial.print("gas rfm = "); 201 | Serial.println(gas_sensor); 202 | }//end if send RFM 203 | }//end if time_passed > 204 | 205 | //=================================================================== 206 | 207 | //delay(100); 208 | 209 | //=================================================================== 210 | //device #3 211 | //flame 212 | 213 | time_passed = millis() - flame_time; 214 | if (time_passed < 0) 215 | { 216 | flame_time = millis(); 217 | flame_time_send = -70000; 218 | } 219 | if (time_passed > 2000) //how often to examine the flame sensor analog value 220 | { 221 | flame_time = millis(); //update time when sensor value last read 222 | flame_status = 0; 223 | flameValue = 0; 224 | 225 | //analog value: usually 1023 for no fire, lower for fire. 226 | flameValue = analogRead(flameAnalogInput); 227 | if ((flameValue < (flameValue_previous - 20)) || ((flameValue > (flameValue_previous + 20)) || (705000 < (millis() - flame_time_send))) ) 228 | { 229 | flame_time_send = millis(); //update gas_time_send with when sensor value last transmitted 230 | theData.deviceID = 3; 231 | theData.var1_usl = millis(); 232 | theData.var2_float = flameValue; 233 | theData.var3_float = flameValue + 100; 234 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 235 | flameValue_previous = flameValue; 236 | 237 | Serial.print("flame detected rfm"); 238 | Serial.println(flameValue); 239 | delay(2000); 240 | } 241 | 242 | 243 | //start debug code 244 | if (debug){ 245 | Serial.print("flame analog = "); 246 | Serial.print(flameValue); 247 | 248 | //analog value: usually 1023 for no fire, lower for fire. 249 | if (flameValue > 1000) 250 | { 251 | flame_status = 0; 252 | Serial.println(" no fire"); 253 | } 254 | else 255 | { 256 | flame_status = 1; 257 | Serial.println(" fire!!!"); 258 | } 259 | }//end debug text 260 | }// end if millis time_passed > 261 | 262 | //=================================================================== 263 | //device #4 264 | //PIR 265 | 266 | //1 mean presence detected? 267 | PIR_reading = digitalRead(PirInput); 268 | //if (PIR_reading == 1) 269 | //Serial.println("PIR = 1"); 270 | //else 271 | //Serial.println("PIR = 0"); 272 | //send PIR sensor value only if presence is detected and the last time 273 | //presence was detected is over x miniutes ago. Avoid excessive RFM sends 274 | if ((PIR_reading == 1) && ( ((millis() - pir_time)>60000)||( (millis() - pir_time)< 0)) ) //meaning there was sound 275 | { 276 | pir_time = millis(); //update gas_time_send with when sensor value last transmitted 277 | theData.deviceID = 4; 278 | theData.var1_usl = millis(); 279 | theData.var2_float = 1111; 280 | theData.var3_float = 1112; //null value; 281 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 282 | Serial.println("PIR detectedEDED RFM"); 283 | delay(2000); 284 | } 285 | 286 | 287 | //=================================================================== 288 | //device #5 289 | //sound 290 | 291 | 292 | //soundValue = analogRead(soundAnalogInput); 293 | //Serial.print("sound analog = "); 294 | //Serial.print(soundValue); 295 | 296 | // 1 = no noise, 0 = noise!! 297 | sound_reading = digitalRead(soundInput); 298 | //Serial.print("sound value = "); 299 | //Serial.println(sound_reading); 300 | if ((sound_reading == 0) && ( ((millis() - sound_time)>20000)||( (millis() - sound_time)< 0)) ) //meaning there was sound 301 | { 302 | sound_time = millis(); //update gas_time_send with when sensor value last transmitted 303 | 304 | theData.deviceID = 5; 305 | theData.var1_usl = millis(); 306 | theData.var2_float = 2222; 307 | theData.var3_float = 2223; //null value; 308 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 309 | Serial.print("sound noise detected RFM "); 310 | sound_reading_previous = sound_reading; 311 | } 312 | 313 | 314 | /* 315 | if (sound_reading == 1) 316 | sound_status = 0; 317 | else 318 | sound_status = 1; 319 | if (sound_status == 1) //noise! 320 | { 321 | Serial.print("sound noise = "); 322 | Serial.println(sound_reading); 323 | } 324 | */ 325 | 326 | 327 | /* 328 | // analog value lower = louder 329 | if (soundValue < 200) 330 | { 331 | sound_status = 1; 332 | Serial.println(" loud"); 333 | } 334 | else 335 | { 336 | sound_status = 0; 337 | Serial.println(" not loud!!!"); 338 | } 339 | */ 340 | 341 | //delay(100); 342 | 343 | //=================================================================== 344 | //device #6 345 | //temperature / humidity 346 | time_passed = millis() - temperature_time; 347 | if (time_passed < 0) 348 | { 349 | temperature_time = millis(); 350 | } 351 | 352 | if (time_passed > 360000) 353 | { 354 | float h = dht.readHumidity(); 355 | // Read temperature as Celsius 356 | float t = dht.readTemperature(); 357 | // Read temperature as Fahrenheit 358 | float f = dht.readTemperature(true); 359 | 360 | // Check if any reads failed and exit early (to try again). 361 | if (isnan(h) || isnan(t) || isnan(f)) { 362 | Serial.println("Failed to read from DHT sensor!"); 363 | return; 364 | } 365 | Serial.print("Humidity="); 366 | Serial.print(h); 367 | Serial.print(" Temp="); 368 | Serial.println(f); 369 | temperature_time = millis(); 370 | 371 | //send data 372 | theData.deviceID = 6; 373 | theData.var1_usl = millis(); 374 | theData.var2_float = f; 375 | theData.var3_float = h; 376 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 377 | delay(1000); 378 | 379 | } 380 | //=================================================================== 381 | //=================================================================== 382 | //device #7 383 | //light 384 | 385 | time_passed = millis() - light_time; 386 | if (time_passed < 0) 387 | { 388 | light_time = millis(); 389 | light_time_send = -70000; 390 | } 391 | if (time_passed > 2000) //how often to examine the sensor analog value 392 | { 393 | light_time = millis(); //update time when sensor value last read 394 | lightValue = 0; 395 | 396 | //analog value: Less than 100 is dark. greater than 500 is room lighting 397 | lightValue = analogRead(lightAnalogInput); 398 | if ((lightValue < (lightValue_previous - 50)) || ((lightValue > (lightValue_previous + 100)) || (705000 < (millis() - light_time_send))) ) 399 | { 400 | light_time_send = millis(); //update gas_time_send with when sensor value last transmitted 401 | theData.deviceID = 7; 402 | theData.var1_usl = millis(); 403 | theData.var2_float = lightValue; 404 | theData.var3_float = lightValue + 20; 405 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 406 | lightValue_previous = lightValue; 407 | Serial.print("light RFM ="); 408 | Serial.println(lightValue); 409 | } 410 | 411 | //start debug code 412 | if (debug) 413 | { 414 | Serial.print("light analog = "); 415 | Serial.println(lightValue); 416 | } 417 | //analog value: usually 1023 for no fire, lower for fire. 418 | 419 | }// end if millis time_passed > 420 | 421 | }//end loop 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | -------------------------------------------------------------------------------- /UberSensor_OpenHAB_Config.txt: -------------------------------------------------------------------------------- 1 | //OpenHAB Configuration for UberSensor.ino 2 | 3 | 4 | /* Item Definition Uber sensor Alarms and Notifications Control*/ 5 | Switch itm_NAA_auto "Auto Schedule Alarms/Notifications" 6 | 7 | Switch itm_uber1_gas_alm_enb "Gas / Smoke Notifer" 8 | Switch itm_uber1_flame_alm_enb "Flame Notifier" 9 | Switch itm_uber1_bark_alm_enb "Bark Notifier" 10 | Switch itm_uber1_pir_alm_enb "Presence Notifier" 11 | 12 | Switch itm_uber1_gas_alm_sta "Gas / Smoke Alarm Status" 13 | Switch itm_uber1_flame_alm_sta "Flame Alarm Status" 14 | Switch itm_uber1_bark_alm_sta "Bark Alarm Status" 15 | Switch itm_uber1_pir_alm_sta "PIR Presence Status" 16 | 17 | Switch itm_uber1_light_sta "Living Room Light" 18 | 19 | DateTime itm_uber1_gas_time "Gas Alarm Time [%1$tA, %1$tm/%1$td, %1$tI:%1$tM %1$tp]" 20 | DateTime itm_uber1_flame_time "Flame Alarm Time [%1$tA, %1$tm/%1$td, %1$tI:%1$tM %1$tp]" 21 | DateTime itm_uber1_bark_time "Bark Alarm Time [%1$tA, %1$tm/%1$td, %1$tI:%1$tM %1$tp]" 22 | DateTime itm_uber1_pir_time "PIR Presence Alarm Time [%1$tA, %1$tm/%1$td, %1$tI:%1$tM %1$tp]" 23 | 24 | Number itm_uber1_gas_mqtt "Gas [%.1f]" (ALL) {mqtt="<[mymosquitto:1222:state:default]"} 25 | Number itm_uber1_flame_mqtt "Flame [%.1f]" (ALL) {mqtt="<[mymosquitto:1232:state:default]"} 26 | Number itm_uber1_pir_mqtt "PIR [%.1f]" (ALL) {mqtt="<[mymosquitto:1242:state:default]"} 27 | Number itm_uber1_bark_mqtt "Bark [%.1f]" (ALL) {mqtt="<[mymosquitto:1252:state:default]"} 28 | Number itm_uber1_temp_mqtt "Uber Temperature [%.1f]" (ALL) {mqtt="<[mymosquitto:1262:state:default]"} 29 | Number itm_uber1_hum_mqtt "Uber Humidity [%.1f]" (ALL) {mqtt="<[mymosquitto:1263:state:default]"} 30 | Number itm_uber1_light_mqtt "Light Sensor [%.1f]" (ALL) {mqtt="<[mymosquitto:1272:state:default]"} 31 | 32 | 33 | --------------------------------------------------------------------------------- 34 | 35 | 36 | /* Uber sensor rules */ 37 | /* ------------- Uber Sensor -------------------- */ 38 | rule "Uber Lighs" 39 | when 40 | Item itm_uber1_light_mqtt received update 41 | then 42 | if(itm_uber1_light_mqtt.state < 350) 43 | { 44 | sendCommand(itm_uber1_light_sta, OFF) 45 | } 46 | else 47 | { 48 | sendCommand(itm_uber1_light_sta, ON) 49 | } 50 | end 51 | 52 | 53 | /*----- uber - gas/smoke ---------- */ 54 | rule "Uber gas smoke threshold" 55 | when 56 | Item itm_uber1_gas_mqtt received update 57 | then 58 | if((itm_uber1_gas_mqtt.state > 220) && (itm_uber1_gas_alm_enb.state == ON)) 59 | { 60 | sendCommand(itm_uber1_gas_alm_sta, ON) 61 | } 62 | end 63 | 64 | rule "Uber gas smoke response" 65 | when 66 | Item itm_uber1_gas_alm_sta changed from OFF to ON 67 | then 68 | sendMail("ArduinoHomeAutomationOpenHAB@gmail.com", "gas / smoke" , "gas or smoke detected") 69 | //playSound("ding.mp3") 70 | postUpdate(itm_uber1_gas_time, new DateTimeType()) 71 | end 72 | 73 | /* --------- uber flame ---------- */ 74 | rule "Uber flame threshold" 75 | when 76 | Item itm_uber1_flame_mqtt received update 77 | then 78 | if((itm_uber1_flame_mqtt.state < 900) && (itm_uber1_flame_alm_enb.state == ON)) 79 | { 80 | sendCommand(itm_uber1_flame_alm_sta, ON) 81 | } 82 | end 83 | 84 | rule "Uber flame response" 85 | when 86 | Item itm_uber1_flame_alm_sta changed from OFF to ON 87 | then 88 | sendMail("ArduinoHomeAutomationOpenHAB@gmail.com", "fire detected" , "fire detected") 89 | //playSound("ding.mp3") 90 | postUpdate(itm_uber1_flame_time, new DateTimeType()) 91 | end 92 | 93 | 94 | /* --------- uber bark ---------- */ 95 | rule "Uber bark threshold" 96 | when 97 | Item itm_uber1_bark_mqtt received update 98 | then 99 | if(itm_uber1_bark_alm_enb.state == ON) 100 | { 101 | sendCommand(itm_uber1_bark_alm_sta, ON) 102 | } 103 | end 104 | 105 | rule "Uber bark response" 106 | when 107 | Item itm_uber1_bark_alm_sta changed from OFF to ON 108 | then 109 | sendMail("ArduinoHomeAutomationOpenHAB@gmail.com", "bark detected" , "dog barked!!!") 110 | //playSound("ding.mp3") 111 | postUpdate(itm_uber1_bark_time, new DateTimeType()) 112 | end 113 | 114 | /* --------- uber pir ---------- */ 115 | rule "Uber pir threshold" 116 | when 117 | Item itm_uber1_pir_mqtt received update 118 | then 119 | if(itm_uber1_pir_alm_enb.state == ON) 120 | { 121 | sendCommand(itm_uber1_pir_alm_sta, ON) 122 | } 123 | end 124 | 125 | rule "Uber pir response" 126 | when 127 | Item itm_uber1_pir_alm_sta changed from OFF to ON 128 | then 129 | sendMail("ArduinoHomeAutomationOpenHAB@gmail.com", "pir detected" , "dog pired!!!") 130 | //playSound("ding.mp3") 131 | postUpdate(itm_uber1_pir_time, new DateTimeType()) 132 | end 133 | 134 | 135 | ----------------------------------------------------------------- 136 | Frame label="Uber Sensor" { 137 | Text item=itm_uber1_temp_mqtt 138 | Text item=itm_uber1_hum_mqtt 139 | Switch item=itm_uber1_light_sta 140 | Switch item=itm_NAA_auto 141 | } 142 | Frame label="Uber Sensor Alarm Status" { 143 | Switch item=itm_uber1_gas_alm_sta mappings=[OFF="Off"] 144 | Switch item=itm_uber1_flame_alm_sta mappings=[OFF="Off"] 145 | Switch item=itm_uber1_bark_alm_sta mappings=[OFF="Off"] 146 | Switch item=itm_uber1_pir_alm_sta mappings=[OFF="Off"] 147 | } 148 | Frame label="Uber Sensor Alarm Enable" { 149 | Switch item=itm_uber1_gas_alm_enb 150 | Switch item=itm_uber1_flame_alm_enb 151 | Switch item=itm_uber1_bark_alm_enb 152 | Switch item=itm_uber1_pir_alm_enb 153 | } 154 | -------------------------------------------------------------------------------- /battery_powered_arduino_frizing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsaitsai/OpenHab-RFM69/902973822ce566b35b390994ae70080bf79420a6/battery_powered_arduino_frizing.jpg -------------------------------------------------------------------------------- /battery_powered_arduino_jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsaitsai/OpenHab-RFM69/902973822ce566b35b390994ae70080bf79420a6/battery_powered_arduino_jpg.jpg -------------------------------------------------------------------------------- /dog_tracker.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 9-18-2014 5 | File: dog_GPS_send.ino 6 | Dog Tracker sketch. Sends GPS coordinate to gateway. 7 | 8 | Modifications Needed: 9 | 1) Update encryption string "ENCRYPTKEY" 10 | 2) 11 | */ 12 | 13 | 14 | /* 15 | NOTES: 16 | 1) RFM69 pin: 17 | MOSI = 11 18 | MISO = 12 19 | SCK = 13 20 | SS = 10 21 | 22 | D_pin 5 = poop incline 23 | D_pin 6 = left side 24 | D_pin 7 = right side 25 | */ 26 | 27 | int pin_poop = 5; //poop incline (1 = poop) 28 | int pin_left = 6; //left (1 = upright) 29 | int pin_right = 7; //right (1 = upright) 30 | 31 | 32 | //for RFM69 33 | #include 34 | #include 35 | 36 | 37 | //for GPS: 38 | #include 39 | #include 40 | 41 | 42 | //#include 43 | 44 | 45 | //RFM setup stuff 46 | #define NODEID 42 //unique for each node on same network 47 | #define NETWORKID 101 //the same on all nodes that talk to each other 48 | #define GATEWAYID 1 49 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 50 | //#define FREQUENCY RF69_433MHZ 51 | //#define FREQUENCY RF69_868MHZ 52 | #define FREQUENCY RF69_915MHZ 53 | #define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes! 54 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 55 | #define ACK_TIME 30 // max # of ms to wait for an ack 56 | #define LED 9 // Moteinos have LEDs on D9 57 | #define SERIAL_BAUD 9600 //must be 9600 for GPS, use whatever if no GPS 58 | 59 | //GPS setup stuff 60 | // RX, TX; Pin 3 (RX) of Arduino goes to RX of GPS 61 | SoftwareSerial mySerial(4, 3); 62 | TinyGPS gps; 63 | void gpsdump(TinyGPS &gps); 64 | void printFloat(double f, int digits = 2); 65 | int printalldata = 0; 66 | 67 | //RFM transmission structure 68 | typedef struct { 69 | int nodeID; //node ID (1xx, 2xx, 3xx); 1xx = basement, 2xx = main floor, 3xx = outside 70 | int deviceID; //sensor ID (2, 3, 4, 5) 71 | unsigned long var1_usl; //uptime in ms 72 | float var2_float; //sensor data? 73 | float var3_float; //battery condition? 74 | } Payload; 75 | Payload theData; 76 | 77 | //MQTT topic names 78 | //4221 = temperature 79 | //4222 = normal position, lat 80 | //4223 = normal position, long 81 | //4231 = poop position, deg 82 | //4232 = poop position, lat 83 | //4233 = poop position, long 84 | 85 | 86 | int TRANSMITPERIOD = 2000; //transmit a packet to gateway so often (in ms) 87 | char buff[20]; 88 | //byte sendSize=0; 89 | boolean requestACK = false; 90 | 91 | 92 | 93 | 94 | //timers 95 | unsigned long last_gps = 0; 96 | unsigned long last_poop = 0; 97 | 98 | int poop_deg = 0; 99 | int temperature = 0; 100 | int position_flag = 2; //1 = poop, 2=walking, 3=left side laying down 4=right side laying down 101 | int position_hold = 2; 102 | int position_current = 2; 103 | unsigned long hold_time = 0; 104 | 105 | unsigned long temp_time = 0; //millis time of last temperature send 106 | 107 | RFM69 radio; 108 | 109 | void setup() 110 | { 111 | pinMode(pin_poop, INPUT); 112 | pinMode(pin_left, INPUT); 113 | pinMode(pin_right, INPUT); 114 | 115 | //RFM69 -------------------------------- 116 | Serial.begin(SERIAL_BAUD); 117 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 118 | #ifdef IS_RFM69HW 119 | radio.setHighPower(); //uncomment only for RFM69HW! 120 | #endif 121 | radio.encrypt(ENCRYPTKEY); 122 | char buff[50]; 123 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 124 | Serial.println(buff); 125 | //-------------------------------------- 126 | 127 | //GPS ---------------------------------- 128 | mySerial.begin(9600); 129 | delay(1000); 130 | Serial.println("uBlox Neo 6M"); 131 | Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version()); 132 | Serial.println("by Mikal Hart"); 133 | Serial.println(); 134 | Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS)); 135 | Serial.println(); 136 | 137 | 138 | }//end setup 139 | 140 | 141 | 142 | //delete? 143 | long lastPeriod = -1; 144 | int mycounter = 1; //not really used for much, just counting radio sends 145 | 146 | void loop() { 147 | //process any serial input 148 | //check for any received packets. Not need for Dog transmitter, but kept for future 149 | if (radio.receiveDone()) 150 | { 151 | Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); 152 | for (byte i = 0; i < radio.DATALEN; i++) 153 | Serial.print((char)radio.DATA[i]); 154 | Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); 155 | 156 | if (radio.ACK_REQUESTED) 157 | { 158 | radio.sendACK(); 159 | Serial.print(" - ACK sent"); 160 | delay(10); 161 | } 162 | //Blink(LED,5); 163 | Serial.println(); 164 | } 165 | 166 | //read digital inputs for dog position 167 | bool pos_poop, pos_left, pos_right; //digital input results 168 | pos_poop = digitalRead(pin_poop); 169 | pos_left = digitalRead(pin_left); 170 | pos_right = digitalRead(pin_right); 171 | 172 | 173 | //determine instantaneous dog disposition 174 | if ((pos_poop == 0) && (pos_left == 1) && (pos_right == 1)) //upright 175 | { 176 | position_current = 2; 177 | } 178 | else if ((pos_left == 0) && (pos_right == 1)) //left 179 | { 180 | position_current = 3; 181 | } 182 | else if ((pos_left == 1) && (pos_right == 0)) //right 183 | { 184 | position_current = 4; 185 | } 186 | else if ((pos_poop == 1) && (pos_left == 1) && (pos_right == 1)) //poop 187 | { 188 | position_current = 1; 189 | } 190 | 191 | //debounce position 192 | if (position_current == position_hold) 193 | { 194 | //do nothing 195 | } 196 | if (position_current != position_hold) 197 | { 198 | hold_time = millis(); 199 | position_hold = position_current; 200 | } 201 | if ((millis() - hold_time) > 5500) //if position held for more than x ms 202 | { 203 | position_flag = position_hold; 204 | } 205 | 206 | 207 | //integer divisions are floor functions 208 | //millis() roll over assumed not an issues (50 days) 209 | int currPeriod = millis()/TRANSMITPERIOD; 210 | 211 | //sends GPS data asynchronously with GPS coordinate updates 212 | //sends GPS data every TRANSITPERIOD 213 | //if (currPeriod != lastPeriod) 214 | Serial.print(" last GPS"); 215 | Serial.print(last_gps); 216 | Serial.print(" millis"); 217 | Serial.println(millis()); 218 | 219 | 220 | if ((millis() - last_gps) > 2500) 221 | { 222 | //lastPeriod=currPeriod; 223 | last_gps = millis(); 224 | 225 | //fill struct w/ values. Assume var2 and var3 already filled 226 | Serial.println("===== tag sending data"); 227 | mycounter = mycounter + 1; 228 | theData.nodeID = NODEID; //identifies the sending node 229 | if (position_flag == 1) //1 = poop 230 | { 231 | Serial.println("Pooping"); 232 | theData.deviceID = 3; //3=poop 233 | theData.var1_usl = poop_deg; 234 | } 235 | else if ((position_flag > 1) || (position_flag==0)) 236 | { 237 | Serial.println("Regular"); 238 | theData.deviceID = 2; //2 = not poop 239 | theData.var1_usl = position_flag; //2=walking, 3=left side laying down 4=right side laying down 240 | } 241 | 242 | //for now, send mycounter. Later, send temperature 243 | //theData.var1_usl = mycounter; //counter...for curiosity sake 244 | //byte temperature = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient 245 | //byte fTemp = 1.8 * temperature + 32; // 9/5=1.8 246 | //theData.var1 = fTemp; 247 | 248 | //send data! 249 | //theData.var2_float = 44.702388; 250 | //theData.var3_float = -93.230855; 251 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 252 | Serial.println("Data sent!"); 253 | 254 | if ((millis() - temp_time)>70000) 255 | { 256 | temp_time = millis(); 257 | 258 | delay(2000); 259 | byte temperature = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient 260 | int fTemp = 1.8 * temperature + 32; // 9/5=1.8 261 | theData.deviceID = 4; //4241 is temperature 262 | theData.var1_usl = fTemp; 263 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 264 | } 265 | } 266 | 267 | 268 | //GPS 269 | bool newdata = false; 270 | unsigned long start = millis(); 271 | 272 | // Every x seconds look for new data from GPS module 273 | while ((millis() - start) < 1500) 274 | { 275 | if (mySerial.available()) 276 | { 277 | //Serial.println("avialable new serial data"); 278 | char c = mySerial.read(); 279 | //Serial.print(c); // uncomment to see raw GPS data 280 | if (gps.encode(c)) 281 | { 282 | newdata = true; 283 | break; // uncomment to print new data immediately! 284 | }//end if gps 285 | newdata = true; //kind of forgot why I have two of these...seems to work ok. 286 | }//end if 287 | }//end while 288 | 289 | if (newdata) { 290 | if (printalldata == 1) 291 | { 292 | Serial.println("Acquired Data"); 293 | Serial.println("-------------"); 294 | } 295 | gpsdump(gps); 296 | if (printalldata == 1) 297 | { 298 | Serial.println("-------------"); 299 | Serial.println(); 300 | } 301 | }//end if newdata 302 | }//end loop 303 | 304 | //not important 305 | void Blink(byte PIN, int DELAY_MS) 306 | { 307 | pinMode(PIN, OUTPUT); 308 | digitalWrite(PIN,HIGH); 309 | delay(DELAY_MS); 310 | digitalWrite(PIN,LOW); 311 | } 312 | 313 | 314 | //Split up GPS data into individual variables. 315 | //This function is where we're taking latitude and longtitude and 316 | //stuffing it into the wireless transmission data structure 317 | //theData.var2_float, theData.var3_float 318 | void gpsdump(TinyGPS &gps) 319 | { 320 | long lat, lon; 321 | float flat, flon; 322 | unsigned long age, date, time, chars; 323 | int year; 324 | byte month, day, hour, minute, second, hundredths; 325 | unsigned short sentences, failed; 326 | 327 | gps.get_position(&lat, &lon, &age); 328 | //Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon); 329 | //Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); 330 | 331 | // On Arduino, GPS characters may be lost during lengthy Serial.print() 332 | // On Teensy, Serial prints to USB, which has large output buffering and 333 | // runs very fast, so it's not necessary to worry about missing 4800 334 | // baud GPS characters. 335 | 336 | gps.f_get_position(&flat, &flon, &age); 337 | if (printalldata == 1) 338 | Serial.print("Lat/Long(float): "); 339 | theData.var2_float = flat; 340 | theData.var3_float = flon; 341 | //theData.var2_float = 3; 342 | //theData.var3_float = -92.12345; 343 | printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5); 344 | if (printalldata == 1) 345 | { 346 | Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); 347 | } 348 | gps.get_datetime(&date, &time, &age); 349 | //Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): "); 350 | // Serial.print(time); 351 | //Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); 352 | 353 | gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age); 354 | if (printalldata == 1) 355 | { 356 | Serial.print("Date: "); Serial.print(static_cast(month)); Serial.print("/"); 357 | Serial.print(static_cast(day)); Serial.print("/"); Serial.print(year); 358 | Serial.print(" Time: "); Serial.print(static_cast(hour)); Serial.print(":"); 359 | Serial.print(static_cast(minute)); Serial.print(":"); Serial.print(static_cast(second)); 360 | Serial.print("."); Serial.print(static_cast(hundredths)); 361 | Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms."); 362 | } 363 | //Serial.print("Alt(cm): "); Serial.print(gps.altitude()); Serial.print(" Course(10^-2 deg): "); 364 | //Serial.print(gps.course()); Serial.print(" Speed(10^-2 knots): "); Serial.println(gps.speed()); 365 | 366 | if (printalldata == 1) 367 | { 368 | Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.print(" Course(float): "); 369 | printFloat(gps.f_course()); Serial.println(); 370 | //Serial.print("Speed(knots): "); printFloat(gps.f_speed_knots()); 371 | Serial.print(" (mph): "); 372 | printFloat(gps.f_speed_mph()); 373 | //Serial.print(" (mps): "); printFloat(gps.f_speed_mps()); Serial.print(" (kmph): "); 374 | // printFloat(gps.f_speed_kmph()); Serial.println(); 375 | 376 | gps.stats(&chars, &sentences, &failed); 377 | Serial.print(" Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); 378 | Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed); 379 | } 380 | } //end gpsdump 381 | 382 | 383 | //only used for serial monitor print outs, not impact on GPS transmission 384 | void printFloat(double number, int digits) 385 | { 386 | // Handle negative numbers 387 | if (number < 0.0) { 388 | Serial.print('-'); 389 | number = -number; 390 | } 391 | 392 | // Round correctly so that print(1.999, 2) prints as "2.00" 393 | double rounding = 0.5; 394 | for (uint8_t i=0; i 0) 406 | Serial.print("."); 407 | 408 | // Extract digits from the remainder one at a time 409 | while (digits-- > 0) { 410 | remainder *= 10.0; 411 | int toPrint = int(remainder); 412 | Serial.print(toPrint); 413 | remainder -= toPrint; 414 | } 415 | } //end printFloat 416 | -------------------------------------------------------------------------------- /dog_tracker_gateway: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 9-18-2014 5 | File: EthGateway_dog.ino 6 | Modified ethernet gateway. Sends more decimals points to MQTT for GPS coordinate accuracy. 7 | 8 | Modifications Needed: 9 | 1) Update "server" IP 10 | 2) UPdate mac address 11 | */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | //I2C receive device address 18 | const byte MY_ADDRESS = 42; //I2C comms w/ other Arduino 19 | 20 | //Ethernet 21 | byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x31, 0x16 }; 22 | byte server[] = { 192, 168, 1, 45 }; 23 | 24 | IPAddress ip(192,168,2,61); 25 | EthernetClient ethClient; 26 | PubSubClient client(server, 1883, callback, ethClient); 27 | unsigned long keepalivetime=0; 28 | unsigned long MQTT_reconnect=0; 29 | 30 | 31 | //use LED for indicating MQTT connection status. 32 | int led = 7; 33 | bool conn_ok; 34 | 35 | void callback(char* topic, byte* payload, unsigned int length) { 36 | // handle message arrived 37 | } 38 | 39 | 40 | void setup() 41 | { 42 | //ethernet 43 | //Ethernet.begin(mac, ip); 44 | Wire.begin (MY_ADDRESS); 45 | Serial.begin (9600); 46 | 47 | Serial.println("starting"); 48 | 49 | pinMode(led, OUTPUT); 50 | 51 | //wait for IP address 52 | 53 | while (Ethernet.begin(mac) != 1) 54 | 55 | { 56 | Serial.println("Error getting IP address via DHCP, trying again..."); 57 | delay(3000); 58 | } 59 | 60 | //Ethernet.begin(mac, ip); 61 | Serial.println("ethernet OK"); 62 | keepalivetime=millis(); 63 | Wire.onReceive (receiveEvent); 64 | 65 | while (client.connect("arduinoClient") != 1) 66 | { 67 | Serial.println("Error connecting to MQTT"); 68 | delay(3000); 69 | } 70 | MQTT_reconnect = millis(); 71 | Serial.println("setup complete"); 72 | 73 | } // end of setup 74 | 75 | 76 | 77 | volatile struct 78 | { 79 | int nodeID; //node ID (1xx, 2xx, 3xx); 1xx = basement, 2xx = main floor, 3xx = outside 80 | int sensorID; //sensor ID (2, 3, 4, 5) 81 | unsigned long var1_usl; //uptime in ms 82 | float var2_float; //sensor data? 83 | float var3_float; //battery condition? 84 | int var4_int; 85 | } SensorNode; 86 | 87 | int sendMQTT = 0; 88 | volatile boolean haveData = false; 89 | 90 | void loop() 91 | { 92 | 93 | if (haveData) 94 | { 95 | Serial.print ("Received Device ID = "); 96 | Serial.println (SensorNode.sensorID); 97 | Serial.print (" Time = "); 98 | Serial.println (SensorNode.var1_usl); 99 | Serial.print (" var2_float "); 100 | Serial.println (SensorNode.var2_float); 101 | 102 | sendMQTT = 1; 103 | 104 | /* 105 | if (client.connect("arduinoClient")) 106 | { 107 | int varnum = 1; 108 | char buff_topic[6]; 109 | char buff_message[6]; 110 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 111 | Serial.println(buff_topic); 112 | dtostrf (SensorNode.var2_float, 4, 1, buff_message); 113 | client.publish(buff_topic, buff_message); 114 | } 115 | */ 116 | 117 | haveData = false; 118 | } // end if haveData 119 | 120 | 121 | if (sendMQTT == 1) 122 | { 123 | 124 | Serial.println("starting MQTT send"); 125 | 126 | conn_ok = client.connected(); 127 | if (conn_ok==1) 128 | { 129 | digitalWrite(led, HIGH); 130 | Serial.println("MQTT connected OK from MQTT Send"); 131 | } 132 | else 133 | { 134 | digitalWrite(led, LOW); 135 | Serial.println("MQTT NOT connected OK from MQTT Send"); 136 | } 137 | 138 | //no connection, reconnect 139 | if (conn_ok == 0) 140 | { 141 | client.disconnect(); 142 | delay(5000); 143 | while (client.connect("arduinoClient") != 1) 144 | { 145 | digitalWrite(led, LOW); 146 | Serial.println("Error connecting to MQTT"); 147 | delay(4000); 148 | digitalWrite(led, HIGH); 149 | } 150 | digitalWrite(led, HIGH); 151 | Serial.println("reconnected to MQTT"); 152 | MQTT_reconnect = millis(); 153 | } 154 | 155 | 156 | int varnum; 157 | char buff_topic[6]; 158 | char buff_message[12]; 159 | 160 | 161 | 162 | //send var1_usl 163 | varnum = 1; 164 | buff_topic[6]; 165 | buff_message[12]; 166 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 167 | Serial.println(buff_topic); 168 | 169 | float shortcut; 170 | shortcut = SensorNode.var1_usl; 171 | Serial.print("shortcut="); 172 | Serial.println(shortcut); 173 | //dtostrf (SensorNode.var1_usl, 10, 1, buff_message); 174 | dtostrf (shortcut, 4, 5, buff_message); 175 | //Serial.print(" varnum1 = "); 176 | //Serial.println(buff_message); 177 | client.publish(buff_topic, buff_message); 178 | 179 | delay(50); 180 | 181 | //send var2_float 182 | varnum = 2; 183 | buff_topic[6]; 184 | buff_message[7]; 185 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 186 | Serial.println(buff_topic); 187 | dtostrf (SensorNode.var2_float, 4, 5, buff_message); 188 | client.publish(buff_topic, buff_message); 189 | 190 | delay(50); 191 | 192 | //send var3_float 193 | varnum = 3; 194 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 195 | Serial.println(buff_topic); 196 | dtostrf (SensorNode.var3_float, 4, 5, buff_message); 197 | client.publish(buff_topic, buff_message); 198 | 199 | delay(50); 200 | 201 | //send var4_int, RSSI 202 | varnum = 4; 203 | sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum); 204 | Serial.println(buff_topic); 205 | sprintf(buff_message, "%04d%", SensorNode.var4_int); 206 | client.publish(buff_topic, buff_message); 207 | 208 | sendMQTT = 0; 209 | Serial.println("finished MQTT send"); 210 | }//end if sendMQTT 211 | 212 | //client.loop(); 213 | 214 | client.loop(); 215 | 216 | 217 | if ((millis() - MQTT_reconnect) > 60000) 218 | { 219 | conn_ok = client.connected(); 220 | if (conn_ok==1) 221 | { 222 | digitalWrite(led, HIGH); 223 | Serial.println("MQTT connected OK"); 224 | } 225 | else 226 | { 227 | digitalWrite(led, LOW); 228 | Serial.println("MQTT NOT connected OK"); 229 | } 230 | 231 | //no connection, reconnect 232 | if (conn_ok == 0) 233 | { 234 | client.disconnect(); 235 | delay(5000); 236 | while (client.connect("arduinoClient") != 1) 237 | { 238 | digitalWrite(led, LOW); 239 | Serial.println("Error connecting to MQTT"); 240 | delay(4000); 241 | digitalWrite(led, HIGH); 242 | } 243 | digitalWrite(led, HIGH); 244 | } 245 | 246 | Serial.println("MQTT connected checked."); 247 | MQTT_reconnect = millis(); 248 | } 249 | 250 | } // end of loop 251 | 252 | 253 | 254 | 255 | // called by interrupt service routine when incoming data arrives 256 | void receiveEvent (int howMany) 257 | { 258 | if (howMany < sizeof SensorNode) 259 | return; 260 | 261 | // read into structure 262 | byte * p = (byte *) &SensorNode; 263 | for (byte i = 0; i < sizeof SensorNode; i++) 264 | *p++ = Wire.read (); 265 | 266 | haveData = true; 267 | } 268 | -------------------------------------------------------------------------------- /laundry_room.config: -------------------------------------------------------------------------------- 1 | //--------------------------------------- 2 | //Item Definition 3 | //--------------------------------------- 4 | /*Laundry Room */ 5 | //in the folder 6 | //create 3 pngs 7 | // myalarm.png 8 | // myalarm-off.png 9 | // myalarm-on.png 10 | // mylight.png 11 | // myalarm-0.png 12 | // myalarm-1.png 13 | Number itm_laun_dryer_mqtt "Dryer [MAP(laundry.map):%s]" (ALL) {mqtt="<[mymosquitto:3042:state:default]"} 14 | Number itm_laun_washer_mqtt "Washer [MAP(laundry.map):%s]" (ALL) {mqtt="<[mymosquitto:3052:state:default]"} 15 | Switch itm_laun_water_leak_alm_enb "Laundry Water Leak Notifier" 16 | Switch itm_laun_water_leak_alm_sta "Laundry Water Leak Status" 17 | Number itm_laun_water_leak_mqtt "Water Leak" (ALL) {mqtt="<[mymosquitto:3032:state:default]"} 18 | Number itm_laun_temp "Laundry Room Temp [%.1f °F]" (All) {mqtt="<[mymosquitto:3022:state:default]"} 19 | Number itm_laun_hum "Laundry Room Humidity [%.1f %%]" (All) {mqtt="<[mymosquitto:3023:state:default]"} 20 | Number itm_laun_light_mqtt "Light Sensor [%.1f]" (ALL) {mqtt="<[mymosquitto:3062:state:default]"} 21 | Number itm_laun_light_icon "Laundry Room Light" 22 | 23 | 24 | //--------------------------------------- 25 | //Site Map 26 | //--------------------------------------- 27 | Text label="Laundry Room" icon="firstfloor" { 28 | Frame label="Laundry Room Status" 29 | { 30 | Text item=itm_laun_dryer_mqtt valuecolor=[<1="gray",==1="green",>1="red"] labelcolor=[<1="gray",==1="green",>1="red"] 31 | Text item=itm_laun_washer_mqtt valuecolor=[<1="gray",==1="green",>1="red"] labelcolor=[<1="gray",==1="green",>1="red"] 32 | Text item=itm_laun_temp 33 | Text item=itm_laun_hum 34 | Text item=itm_laun_light_icon 35 | Switch item=itm_laun_water_leak_alm_sta mappings=[OFF="Reset"] 36 | //Text item=itm_laun_water_leak_alm_sta valuecolor=[==0="black",==1="red"] labelcolor=[==0="black",==1="red"] 37 | } 38 | Frame label="Alarm Enable" 39 | { 40 | Switch item=itm_laun_water_leak_alm_enb 41 | } 42 | 43 | } 44 | 45 | //--------------------------------------- 46 | //Rules 47 | //--------------------------------------- 48 | rule "Laundry Lights" 49 | when 50 | Item itm_laun_light_mqtt received update 51 | then 52 | if(itm_laun_light_mqtt.state < 350) 53 | { 54 | sendCommand(itm_laun_light_icon, 0) 55 | } 56 | else 57 | { 58 | sendCommand(itm_laun_light_icon, 1) 59 | } 60 | end 61 | 62 | rule "Washer Complete" 63 | when 64 | Item itm_laun_washer_mqtt received update 65 | then 66 | if(itm_laun_washer_mqtt.state == 2) 67 | { 68 | say("Washer Complete!") 69 | } 70 | end 71 | rule "Dryer Complete" 72 | when 73 | Item itm_laun_dryer_mqtt received update 74 | then 75 | if(itm_laun_dryer_mqtt.state == 2) 76 | { 77 | say("Dryer Complete!") 78 | } 79 | end 80 | 81 | /* --------- Laundry Water Leak ---------- */ 82 | rule "Laundry Water Leak" 83 | when 84 | Item itm_laun_water_leak_mqtt received update 85 | then 86 | sendCommand(itm_laun_water_leak_alm_sta, ON) 87 | 88 | end 89 | 90 | rule "Laundry Water Leak response" 91 | when 92 | Item itm_laun_water_leak_alm_sta changed from OFF to ON 93 | then 94 | if(itm_laun_water_leak_alm_enb.state == ON) 95 | { 96 | sendMail("email_Address@domain.com", "laundry water leak" , "laundry water leak detected") 97 | } 98 | //playSound("alarm.mp3") 99 | end 100 | -------------------------------------------------------------------------------- /laundry_room.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Eric Tsai 3 | License: CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/ 4 | Date: 9-22-2014: clean up comment for first post 5 | File: Laundry_room.ino 6 | This sketch is for a wired Arduino w/ RFM69 wireless transceiver 7 | Monitors dryer status, uses PIR sensor to indicate empty load. 8 | Notification for water leaks. 9 | Light sensor. 10 | to gateway. See OpenHAB configuration below. 11 | 12 | 1) Update encryption string "ENCRYPTKEY" 13 | 2) 14 | */ 15 | 16 | /* 17 | OpenHAB configuration 18 | 19 | Item Definition 20 | Number itm_dryer "Dryer is [MAP(laundry.map):%s]" (ALL) {mqtt="<[mymosquitto:3052:state:default]"} 21 | 22 | Sitemap Definition 23 | Text item=itm_dryer valuecolor=[<1="black",==1="green",>1="orange"] labelcolor=[2="orange", 1="green", 0="black"] 24 | 25 | 26 | Create a file in /configuration/transform 27 | 0=Off & Empty 28 | 1=Running 29 | 2=Done 30 | 31 | Reference 32 | https://github.com/openhab/openhab/wiki/Explanation-of-Items 33 | 34 | 35 | 36 | */ 37 | 38 | /* MQTT topic addressing 39 | node = 30 40 | 41 | device ID: 42 | 2 = 3022 = Temperature_F 43 | = 3023 = Humidity 44 | 3 = 3021 = Water Present 45 | 4 = 3042 = Washer status (not implemented) 46 | 5 = 3052 = Dryer status (implemented) 47 | 6 = 3062 = Light 48 | 49 | Pins 50 | A2 = light sensor 51 | 3 = water leak 52 | 5 = PIR sensor 53 | 6 = sound 1 54 | 7 = DHT11 sensor 55 | 8 = sound 2 56 | 57 | 58 | */ 59 | 60 | //RFM69 -------------------------------------------------------------------------------------------------- 61 | #include 62 | #include 63 | #define NODEID 30 //unique for each node on same network 64 | #define NETWORKID 101 //the same on all nodes that talk to each other 65 | #define GATEWAYID 1 66 | //Match frequency to the hardware version of the radio on your Moteino (uncomment one): 67 | //#define FREQUENCY RF69_433MHZ 68 | //#define FREQUENCY RF69_868MHZ 69 | #define FREQUENCY RF69_915MHZ 70 | #define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes! 71 | #define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! 72 | #define ACK_TIME 30 // max # of ms to wait for an ack 73 | #define LED 9 // Moteinos have LEDs on D9 74 | #define SERIAL_BAUD 9600 //must be 9600 for GPS, use whatever if no GPS 75 | boolean debug = 0; 76 | //struct for wireless data transmission 77 | typedef struct { 78 | int nodeID; //node ID (1xx, 2xx, 3xx); 1xx = basement, 2xx = main floor, 3xx = outside 79 | int deviceID; //sensor ID (2, 3, 4, 5) 80 | unsigned long var1_usl; //uptime in ms 81 | float var2_float; //sensor data? 82 | float var3_float; //battery condition? 83 | } Payload; 84 | Payload theData; 85 | char buff[20]; 86 | byte sendSize=0; 87 | boolean requestACK = false; 88 | RFM69 radio; 89 | //end RFM69 ------------------------------------------ 90 | 91 | /* 92 | // gas sensor================================================ 93 | int GasSmokeAnalogPin = 0; // potentiometer wiper (middle terminal) connected to analog pin 94 | int gas_sensor = -500; // gas sensor value, current 95 | int gas_sensor_previous = -500; //sensor value previously sent via RFM 96 | */ 97 | 98 | //temperature / humidity ===================================== 99 | #include "DHT.h" 100 | #define DHTPIN 7 // digital pin we're connected to 101 | #define DHTTYPE DHT11 // DHT 22 (AM2302) blue one 102 | //#define DHTTYPE DHT21 // DHT 21 (AM2301) white one 103 | // Initialize DHT sensor for normal 16mhz Arduino 104 | DHT dht(DHTPIN, DHTTYPE); 105 | 106 | 107 | 108 | // Light sensor =============================================== 109 | int lightAnalogInput = A2; //analog input for photo resistor 110 | int lightValue = -50; 111 | int lightValue_previous = -50; 112 | 113 | // PIR sensor ================================================ 114 | // used to clear a completed load (to know that it's been emptied) 115 | int PirInput = 5; 116 | int PIR_status = 0; 117 | int PIR_reading = 0; 118 | int PIR_reading_previous = 0; 119 | 120 | // sound sensor 1 (Dryer) ============================================== 121 | int soundInput1 = 6; //sound sensor digital input pin 122 | int sound_status1 = 0; 123 | int sound_reading1 = 0; //reading =1 mean no noise, 0=noise 124 | int sound_reading1_previous = 0; 125 | int sound_1_device_state = 0; //1 = running, 0 = empty, 2 = complete 126 | 127 | unsigned long sound_time_1 = 0; //millis of last reading 128 | int sound_count_1 = 0; //number of captures 129 | int sound_detected_count_1 = 0; //number of readings showing sound 130 | 131 | 132 | // water leak sensor ========================================== 133 | unsigned long water_time; 134 | int waterInput = 3; //pin for water detection 135 | int water_reading = 0; //for reading water pin 136 | 137 | 138 | // timings 139 | unsigned long pir_time; 140 | unsigned long sound_time; 141 | unsigned long temperature_time; 142 | unsigned long light_time; 143 | unsigned long light_time_send; 144 | 145 | 146 | void setup() 147 | { 148 | Serial.begin(9600); // setup serial 149 | //RFM69------------------------------------------- 150 | radio.initialize(FREQUENCY,NODEID,NETWORKID); 151 | #ifdef IS_RFM69HW 152 | radio.setHighPower(); //uncomment only for RFM69HW! 153 | #endif 154 | radio.encrypt(ENCRYPTKEY); 155 | char buff[50]; 156 | sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); 157 | Serial.println(buff); 158 | theData.nodeID = NODEID; //this node id should be the same for all devices in this node 159 | //end RFM-------------------------------------------- 160 | 161 | 162 | dht.begin(); //temperature & humidity sensor 163 | 164 | pinMode(soundInput1, INPUT); //sound sensor 1 (dryer) 165 | 166 | pinMode(waterInput, INPUT); //water detection 167 | 168 | //initialize times 169 | sound_time = millis(); 170 | temperature_time = millis(); 171 | pinMode(PirInput, INPUT); //PIR sensor 172 | } 173 | void loop() 174 | { 175 | unsigned long time_passed = 0; 176 | 177 | 178 | 179 | 180 | //=============================================================== 181 | //Water Leak sensor 182 | //Device #3 183 | //=============================================================== 184 | water_reading = digitalRead(waterInput); //0 = no water, 1 = water (backwards) 185 | if (water_reading) 186 | Serial.println("no water"); 187 | else 188 | { 189 | Serial.println("water det "); 190 | delay(1000); 191 | } 192 | 193 | if ((water_reading == 0) && ( ((millis() - water_time)>7000)||( (millis() - water_time)< 0)) ) //meaning there was sound 194 | { 195 | water_time = millis(); //update gas_time_send with when sensor value last transmitted 196 | 197 | theData.deviceID = 3; 198 | theData.var1_usl = millis(); 199 | theData.var2_float = 1; 200 | theData.var3_float = 101; //null value; 201 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 202 | Serial.print("water detected!!! "); 203 | 204 | } 205 | 206 | 207 | //=================================================================== 208 | //device PIR 209 | //note: this PIR sensor goes straight to I/O, no pull down resistor. 210 | // 1 = detected movement 211 | PIR_reading = digitalRead(PirInput); 212 | //if (PIR_reading == 1) 213 | //Serial.println("PIR = 1"); 214 | //else 215 | //Serial.println("PIR = 0"); 216 | 217 | // if someone is in the laundry room and washer/dryer is complete (not emptied) 218 | if ((PIR_reading == 1) && (sound_1_device_state == 2)) 219 | { 220 | sound_1_device_state = 0; 221 | theData.deviceID = 5; 222 | theData.var1_usl = millis(); 223 | theData.var2_float = 0; 224 | theData.var3_float = 11223; //null value; 225 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 226 | } 227 | 228 | 229 | //=================================================================== 230 | //device #5 231 | //Dryer Running Sound Sensor 232 | 233 | //soundValue = analogRead(soundAnalogInput); 234 | //Serial.print("sound analog = "); 235 | //Serial.print(soundValue); 236 | 237 | 238 | //deal with millis rollover 239 | if (sound_time_1 > millis()) 240 | { 241 | sound_time_1 = millis(); 242 | } 243 | 244 | //capture sound as fast as we can. If there is sound, mark it as so. 245 | int sound = digitalRead(soundInput1); 246 | if (sound == 0) 247 | { 248 | sound_reading1 = 0; 249 | } 250 | 251 | //count sound as for real only every 1/2 second. 252 | if ((millis() - sound_time_1)>500) 253 | { 254 | sound_time_1 = millis(); //reset sound_time_1 to wait for next Xms 255 | 256 | //sound_reading1 = digitalRead(soundInput1); // 1 = no noise, 0 = noise!! 257 | 258 | /* 259 | Serial.print(sound_count_1); 260 | Serial.print(" out of "); 261 | Serial.print(sound_detected_count_1); 262 | Serial.print(" state= "); 263 | Serial.print(sound_1_device_state); 264 | if (!sound_reading1) 265 | Serial.println(" sound detected"); 266 | else 267 | Serial.println(" no sound detected"); 268 | */ 269 | 270 | sound_count_1 = sound_count_1 + 1; //count how many times we listened 271 | if (sound_reading1 == 0) //count how many times detected sound 272 | { 273 | sound_detected_count_1 = sound_detected_count_1 + 1; 274 | } 275 | 276 | sound_reading1 = 1; //reset back to no sound (1 = no sound) 277 | }//end reading every second 278 | 279 | //after X number of sound checks... 280 | if (sound_count_1 >= 30) 281 | { 282 | //sound_count_1 = number of times sensor listened 283 | //sound_detected_count_1 = number of times heard sound 284 | //sound_1_device_state: 0=emptied, 1=running, 2=cycle complete (but not emptied) 285 | 286 | // sound_1_device_state = 1 = running 287 | Serial.print("checking checking evaluating sound"); 288 | if ((sound_detected_count_1 >= 5) && ((sound_1_device_state == 0) || (sound_1_device_state == 2))) //number of times sensor registered sound 289 | { 290 | //Serial.println("running!"); 291 | sound_1_device_state = 1; 292 | 293 | theData.deviceID = 4; 294 | theData.var1_usl = millis(); 295 | theData.var2_float = 1; //1 = device running 296 | theData.var3_float = 11223; //doesn't mean a thing 297 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 298 | } 299 | 300 | // sound_1_device_state = 2 = Cycle complete (but not emptied) 301 | else if ((sound_detected_count_1 < 3) && (sound_1_device_state == 1)) 302 | { 303 | //Serial.println("not running!!"); 304 | sound_1_device_state = 2; 305 | 306 | theData.deviceID = 5; 307 | theData.var1_usl = millis(); 308 | theData.var2_float = 2; 309 | theData.var3_float = 11223; //null value; 310 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 311 | 312 | //reset how often sensor has listened and how many sound events detected 313 | } 314 | sound_count_1 = 0; 315 | sound_detected_count_1 = 0; 316 | } //end if count_count_1 317 | 318 | 319 | //=================================================================== 320 | //device #2 321 | //temperature / humidity 322 | time_passed = millis() - temperature_time; 323 | if (time_passed < 0) 324 | { 325 | temperature_time = millis(); 326 | } 327 | 328 | //only report temps/humidity after X seconds 329 | if (time_passed > 360000) 330 | { 331 | float h = dht.readHumidity(); 332 | // Read temperature as Celsius 333 | float t = dht.readTemperature(); 334 | // Read temperature as Fahrenheit 335 | float f = dht.readTemperature(true); 336 | // Check if any reads failed and exit early (to try again). 337 | if (isnan(h) || isnan(t) || isnan(f)) { 338 | Serial.println("Failed to read from DHT sensor!"); 339 | return; 340 | } 341 | Serial.print("Humidity="); 342 | Serial.print(h); 343 | Serial.print(" Temp="); 344 | Serial.println(f); 345 | temperature_time = millis(); 346 | //send data 347 | theData.deviceID = 2; 348 | theData.var1_usl = millis(); 349 | theData.var2_float = f; 350 | theData.var3_float = h; 351 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 352 | delay(1000); 353 | } 354 | 355 | 356 | //=================================================================== 357 | //device #6 358 | //light 359 | time_passed = millis() - light_time; 360 | if (time_passed < 0) 361 | { 362 | light_time = millis(); 363 | light_time_send = -70000; 364 | } 365 | if (time_passed > 2000) //how often to examine the sensor analog value 366 | { 367 | light_time = millis(); //update time when sensor value last read 368 | lightValue = 0; 369 | //analog value: Less than 100 is dark. greater than 500 is room lighting 370 | lightValue = analogRead(lightAnalogInput); 371 | if ((lightValue < (lightValue_previous - 50)) || ((lightValue > (lightValue_previous + 100)) || (705000 < (millis() - light_time_send))) ) 372 | { 373 | light_time_send = millis(); 374 | theData.deviceID = 6; 375 | theData.var1_usl = millis(); 376 | theData.var2_float = lightValue; 377 | theData.var3_float = lightValue + 20; 378 | radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)); 379 | lightValue_previous = lightValue; 380 | Serial.print("light RFM ="); 381 | Serial.println(lightValue); 382 | } 383 | //start debug code 384 | if (0) 385 | { 386 | Serial.print("light analog = "); 387 | Serial.println(lightValue); 388 | } 389 | 390 | }// end if millis time_passed > 391 | }//end loop 392 | 393 | --------------------------------------------------------------------------------