Mysensors 2.0 + Relay, DHT, and PIR - No Relay
-
Hello folks:
I'm trying to put together a powered multi sensor using mysensors 2, that will have a DHT, PIR, and a relay to act as a quick trigger for the garage. ( momentary push ), but I can't seem to get the relay to trigger with the following sketch:
/** DHT-Motion, MySensors 2.0.0, motion sensor pin 3, DHT pin 7 */ // Enable debug prints #define MY_DEBUG #define MY_NODE_ID 50 // My Node ID variable // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 //#define MY_RS485 #include <SPI.h> #include <MySensors.h> #include <DHT.h> // Set this to the pin you connected the DHT's data pin to #define DHT_DATA_PIN 7 #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) // Set this offset if the sensor has a permanent small offset to the real temperatures #define SENSOR_TEMP_OFFSET -1 // Sleep time between sensor updates (in milliseconds) // Must be >1000ms for DHT22 and >2000ms for DHT11 static const uint64_t UPDATE_INTERVAL = 60000; // Force sending an update of the temperature after n sensor reads, so a controller showing the // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that // the value didn't change since; // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms] static const uint8_t FORCE_UPDATE_N_READS = 10; #define CHILD_ID_MO 3 #define CHILD_ID_HUM 10 #define CHILD_ID_TEMP 11 #define RELAY_1 4 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define CHILD_ID_OPENER 0 #define CHILD_ID_STATUS 1 #define TOGGLE_INTERVAL 350 //Tells how many milliseconds the relay will be held closed #define CLOSED 0 #define OPEN 1 DHT dht; float lastTemp; float lastHum; uint8_t nNoUpdatesTemp; uint8_t nNoUpdatesHum; bool metric = true; MyMessage msgMot(CHILD_ID_MO, V_TRIPPED); MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); MyMessage msgOpener(CHILD_ID_OPENER, V_STATUS); MyMessage msgStatus(CHILD_ID_STATUS, V_TEXT); void presentation() { // Send the sketch version information to the gateway sendSketchInfo("DHT-Motion_Relay", "1.1"); // Register all sensors to gw (they will be created as child devices) present(CHILD_ID_MO, S_MOTION); wait(30); present(CHILD_ID_HUM, S_HUM); wait(30); present(CHILD_ID_TEMP, S_TEMP); wait(30); sendHeartbeat(); wait(30); present(CHILD_ID_OPENER, S_BINARY); wait(30); present(CHILD_ID_STATUS, S_INFO); wait(30); } void setup() { pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) { Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!"); } // Sleep for the time of the minimum sampling period to give the sensor time to power up // (otherwise, timeout errors might occure for the first reading) sleep(dht.getMinimumSamplingPeriod()); pinMode(RELAY_1, OUTPUT); digitalWrite(RELAY_1, loadState(RELAY_1)?RELAY_OFF:RELAY_ON); } void loop() { // Force reading sensor, so it works also after sleep() dht.readSensor(true); // Get temperature from DHT library float temperature = dht.getTemperature(); if (isnan(temperature)) { Serial.println("Failed reading temperature from DHT!"); } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) { // Only send temperature if it changed since the last measurement or if we didn't send an update for n times lastTemp = temperature; if (!metric) { temperature = dht.toFahrenheit(temperature); } // Reset no updates counter nNoUpdatesTemp = 0; temperature += SENSOR_TEMP_OFFSET; send(msgTemp.set(temperature, 1)); wait(50); #ifdef MY_DEBUG Serial.print("T: "); Serial.println(temperature); #endif } else { // Increase no update counter if the temperature stayed the same nNoUpdatesTemp++; } // Get humidity from DHT library float humidity = dht.getHumidity(); if (isnan(humidity)) { Serial.println("Failed reading humidity from DHT"); } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) { // Only send humidity if it changed since the last measurement or if we didn't send an update for n times lastHum = humidity; // Reset no updates counter nNoUpdatesHum = 0; send(msgHum.set(humidity, 1)); wait(50); #ifdef MY_DEBUG Serial.print("H: "); Serial.println(humidity); #endif } else { // Increase no update counter if the humidity stayed the same nNoUpdatesHum++; } // Read digital motion value bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; Serial.println(tripped); send(msgMot.set(tripped?"1":"0")); // Send tripped value to gw wait(300); // Sleep for a while to save energy sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, UPDATE_INTERVAL); } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type==V_LIGHT) { // Change relay state digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); digitalWrite( RELAY_1, RELAY_ON ); //Keep the relay on for the amount of time defined by TOGGLE_INTERVAL delay( TOGGLE_INTERVAL ); digitalWrite( RELAY_1, RELAY_OFF ); //Added this to tell the controller that we shut off the relay // Store state in eeprom saveState(message.sensor, message.getBool()); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.getBool()); } }
Can anyone help with where I have gone wrong? Board, NRF, etc all work with the default relay sketch, but when I am combining, I am not having any luck with the relay, everything else appears fine based on serial output:
Starting sensor (RNNNA-, 2.0.0) TSM:INIT TSM:RADIO:OK TSP:ASSIGNID:OK (ID=50) TSM:FPAR TSP:MSG:SEND 50-50-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc: TSP:MSG:READ 0-0-50 s=255,c=3,t=8,pt=1,l=1,sg=0:0 TSP:MSG:FPAR RES (ID=0, dist=0) TSP:MSG:PAR OK (ID=0, dist=1) TSM:FPAR:OK TSM:ID TSM:CHKID:OK (ID=50) TSM:UPL TSP:PING:SEND (dest=0) TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=ok:1 TSP:MSG:READ 0-0-50 s=255,c=3,t=25,pt=1,l=1,sg=0:1 TSP:MSG:PONG RECV (hops=1) TSP:CHKUPL:OK TSM:UPL:OK TSM:READY TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=ok:0100 !TSP:MSG:SEND 50-50-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=fail:2.0.0 TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,ft=1,st=ok:0 TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=11,pt=0,l=16,sg=0,ft=0,st=ok:DHT-Motion_Relay TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=ok:1.1 TSP:MSG:SEND 50-50-0-0 s=3,c=0,t=1,pt=0,l=0,sg=0,ft=0,st=ok: TSP:MSG:SEND 50-50-0-0 s=10,c=0,t=7,pt=0,l=0,sg=0,ft=0,st=ok: TSP:MSG:SEND 50-50-0-0 s=11,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=ok: TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=22,pt=5,l=4,sg=0,ft=0,st=ok:2197 TSP:MSG:SEND 50-50-0-0 s=0,c=0,t=3,pt=0,l=0,sg=0,ft=0,st=ok: TSP:MSG:READ 0-0-50 s=255,c=3,t=6,pt=0,l=1,sg=0:M TSP:MSG:SEND 50-50-0-0 s=1,c=0,t=36,pt=0,l=0,sg=0,ft=0,st=ok: Request registration... TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=ok:2 TSP:MSG:READ 0-0-50 s=255,c=3,t=27,pt=1,l=1,sg=0:1 Node registration=1 Init complete, id=50, parent=0, distance=1, registration=1 TSP:MSG:SEND 50-50-0-0 s=11,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=ok:20.0 T: 20.00 TSP:MSG:SEND 50-50-0-0 s=10,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=ok:23.0 H: 23.00 0 TSP:MSG:SEND 50-50-0-0 s=3,c=1,t=16,pt=0,l=1,sg=0,ft=0,st=ok:0
-
@rhuehn - what does it look like when you send the trigger command? Do you get anything in the node log?
-
Isn't it so, that this code block makes the node unresponsive for UPDATE_INTERVAL 60 s? The only exception would be the digital input 3 (PIR pin).
// Sleep for a while to save energy sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, UPDATE_INTERVAL); nsert Code Here
-
Hello @Nuubi Yes I believe that is exactly why the Relay goes unresponsive. If I remove that sleep block, the PIR floods the gateway, and I am not sure how to get around it? Is there any possible recommendations you could make to the code so that the DHT, PIR AND Relay all work without the PIR flooding the gateway?
Thanks very much!
-
@rhuehn - you could with a if statement only send if the value is changed.
-
I did a similar project that is working well. Mine was powered all the time, so I didn't use the sleep code. The main reason I didn't was so that I could manually control the relay/light when there was no motion detected. It also allowed me to get continuous readings from the LDR so I could use that light level for other things if I ever wanted to.
Here is a link to my project. https://forum.mysensors.org/topic/5243/driveway-motion-light . Maybe you can get some ideas from my code.