|
Post by selcouth on Apr 1, 2015 2:55:22 GMT
After spending a few hours playing with pull up resistors from 3.3k up to 20k I couldn't get my PIR sensor working well with the DHT end node sketch. Pretty much any other activity on the Arudino would trigger a HIGH read on the digital input line for the PIR sensor. So I decided to handle it with analogRead instead. Working well now so I figured I would share my setup.
I had a magnetic reed switch on digital pin 8 using dev40, so I originally set out to use digital pin 7 and dev41 for the PIR sensor. Later changed to analog A0 but still used dev41.
Code snippets:
... #define BI2PIN A0 // Analog binary input pin for PIR, devID 41 ... // "BI2" is my shorthand for Binary Input 2 long lastTimeBI2 = -1; // timestamp last BI2 input bool curStateBI2 = true; // current BI2 state bool lastStateBI2 = true; // last BI2 state ... // begin BI2 input detection if (analogRead(BI2PIN) > 800) { //my PIR sensor trips 1023 when active (HIGH) curStateBI2 = 1; } else { curStateBI2 = 0; } msgBlock = ((millis() - lastTimeBI2) < HOLDOFF); // hold-off time for additional BI2 messages if (!msgBlock && (curStateBI2 != lastStateBI2)) { // input changed ? delay(5); lastTimeBI2 = millis(); // take timestamp send41 = true; // set BI2 message flag lastStateBI2 = curStateBI2; } //end BI2 input detection
EDIT:
Well, scratch that. Added another sensor and now A0 is reading 1023 when other activity is happening. Back to the drawing board.
EDIT 2:
Looks like it might be related to RF interference. I've placed the PIR sensor on 10 feet of CAT5E cable and initial tests with analogRead are working again. I'll play with it more tomorrow to verify.
|
|
|
Post by computourist on Apr 1, 2015 8:48:45 GMT
You could try without the pull-up resistor. Your PIR module delivers a digital TTL output with voltage 3.3 Volts. On a 3.3 Volts Arduino you should be able to detect this signal without problems.
|
|
|
Post by selcouth on Apr 1, 2015 23:09:47 GMT
I originally tried it without the pull up resistor and had the same results. It's definitely due to interference, and I'm 95% certain it's RF interference. I've moved the sensor back to pin 7 and I'm reading it digitally now with no trouble. The sensor is on a 10 foot cable about 5 feet from the RFM69HW and Arduino.
|
|
|
Post by c0nfused on May 2, 2015 14:16:22 GMT
Computourist how would add a PIR sensor to your DHT end node? I have your 2.2 gateway running with no problems, codeing and openhab is very overwelming.
|
|
|
Post by computourist on May 12, 2015 13:38:14 GMT
Computourist how would add a PIR sensor to your DHT end node? I have your 2.2 gateway running with no problems, codeing and openhab is very overwelming. It depends on your PIR-sensor. If it has a digital output it should work with the digital input on the end-node. Have a look at the datasheet of your device. There are several examples of arduino sketches for PIR sensors on the Internet. I would try one of these first to see if the PIR-sensor is working OK as a digital input.
|
|
|
Post by gandalph on Jun 2, 2015 15:19:44 GMT
I have a PIR added to the DHT node sketch, will post shortly. HW setup is as follows: 3.3v pro mini+RFM69HW+HC-SR501. I put a 10KOhm pullup between data and 3.3v. Also read somewhere that GND from the PIR should be put in the GND nearest RAW (?). Did that too just for good measure. Then hack the PIR to circumvent capacitors etc and supply 3.3v straight to the PIR. (solder 3.3v to the middle of 3 little squares, link to pic in sketch ) PIR is wired to D5. In the software I have incorporated a 2s wait to stabilize the grid, send/rcv activity will trigger the PIR. DHT PIR sketch (v2.2...): // RFM69 node sketch // // This node talks to the MQTT-Gateway and will: // - send sensor data periodically and on-demand // - receive commands from the gateway to control actuators // - receive commands from the gateway to change settings // // Several nodes can operate within a single network; each have a unique node ID. // On startup the node operates with default values, set on compilation. // // Hardware used is a 3.3 Volt 8MHz arduino Pro; this is easier to interface to RFM69 // // A DHT-11 is used for temperature & humidity measurements, other sensors and outputs can be added easily. // // Message format is: nodeID/deviceID/command/integer/float/string // // Depending on the type of data (integer, float or string) one of the payload variables is used // Command = 0 means write a value in the node, cmd = 1 means read a value // // Current defined devices are: // // 0 uptime: read uptime node in minutes // 1 node: read/set transmission interval in seconds, 0 means no periodic transmission // 2 RSSI: read radio signal strength // 3 Version: read version node software // 4 voltage: read battery level // 5 ACK: read/set acknowledge message after a 'set' request // 6 toggle: read/set toggle function on button press // 7 timer: read/set activation timer after button press in seconds, 0 means no timer // // 16 actuator: read/set LED or relay output // 40 Button: tx only: message sent when button pressed // 41 PIR: read presence // 48 temperature: read temperature // 49 humidity: read humidity // 90 error: tx only: error message if no wireless connection (generated by gateway) // 92 error: tx only: device not supported // 99 wakeup: tx only: first message sent on node startup // // The button can be set to: // - generate a message on each press (limited to one per 10 seconds) and/or // - toggle the output ACT1 (local node function) or // - activate the output for a fixed time period (local node function) // // The HC-SR501 PIR can be placed on a 3.3v pro mini arduino using a hack described here: http://forum.mysensors.org/topic/1088/battery-powered-pir // circumventing the need for boost regulators etc. Be sure not to short the circout when rewiring... (re-seperating the pads with a sharp knife after soldering may help) // The PIR sensor is wired to 3.3v, ground (may need to wire to GND pin close to RAW?), and with a 10K Ohm pullup resistor between data and 3.3v. // when talking to openHab over MQTT, the following item config will pick up the PIR ON msg correctly: // String itm_node2_pir_mqtt "PIR [%s]" {mqtt="<[mymosquitto:home/rfm_gw/nb/node02/dev41:command:on]"} // (change node to your node) // // A debug mode is included which outputs messages on the serial output // // RFM69 Library by Felix Rusu - felix@lowpowerlab.com // Get the RFM69 library at: https://github.com/LowPowerLab/ // // version 1.7 by Computourist@gmail.com december 2014 // version 2.0 increased payload size; implemented node uptime; standard device type convention; error handling . // version 2.1 removed device 8; changed handling of device 40; compatible with gateway V2.2 ; march 2015 // version 2.2 added switches for sensors DHT, Button and PIR, added PIR code, added verbose serial output on send; may 2015 by Gandalph @ http://homeautomation.proboards.com/board/2/openhab-rfm69-based-arduino // /*--------------------------------\\//------------------------------*/
// What kind of devices are enabled on this node?: // #define DHT // #define DS18 #define PIR // #define BUTTON
#include <RFM69.h> #include <SPI.h> #ifdef DHT #include <DHT.h> #endif
/* CONFIGURATION PARAMETERS */ #define NODEID 2 // unique node ID within the closed network #define GATEWAYID 1 // node ID of the Gateway is always 1 #define NETWORKID 100 // network ID of the network #define ENCRYPTKEY "xxxxxxxxxxxxxxxx" // 16-char encryption key; same as on Gateway! //#define DEBUG // uncomment for debugging #define VERSION "V2.2" // this value can be queried as device 3 // Wireless settings Match frequency to the hardware version of the radio //#define FREQUENCY RF69_433MHZ #define FREQUENCY RF69_868MHZ //#define FREQUENCY RF69_915MHZ #define IS_RFM69HW // uncomment only for RFM69HW! #define ACK_TIME 50 // max # of ms to wait for an ack #ifdef DHT // DHT 11 / sensor setting //#define DHTPIN 4 // DHT data connection #define DHTPIN A0 // DHT data connection #define DHT11_PIN A0 // analog pin we're connected to #define DHTTYPE DHT11 // type of sensor #endif #define ACT1 9 // Actuator pin (LED or relay) #define BTN 8 // Button pin #define SERIAL_BAUD 115200 #define HOLDOFF 2000 // blocking period between button and PIR messages
/* STARTUP DEFAULTS */ long TXinterval = 60; // periodic transmission interval in seconds long TIMinterval = 20; // timer interval in seconds bool ackButton = false; // flag for message on button press bool toggleOnButton = true; // toggle output on button press
/* VARIABLES */ long lastPeriod = -1; // timestamp last transmission long lastBtnPress = -1; // timestamp last buttonpress long lastPIR = -1; // timestamp last PIR detection long lastMinute = -1; // timestamp last minute long upTime = 0; // uptime in minutes float hum, temp; // humidity, temperature int ACT1State; // status ACT1 output int signalStrength; // radio signal strength bool setAck = false; // send ACK message on 'SET' request bool send0, send1, send2, send3, send4; bool send5, send6, send7; bool send16, send40, send41, send48, send49, send92; // message triggers bool promiscuousMode = false; // only listen to nodes within the closed network bool wakeUp = true; // wakeup flag bool curState = true; // current button state bool lastState = true; // last button state bool curPIRState = true; // current PIR state bool lastPIRState = true; // last PIR state bool timerOnButton = false; // timer output on button press bool msgBlock = false; // flag to hold button messages to prevent overload
typedef struct { // Radio packet format int nodeID; // node identifier int devID; // device identifier int cmd; // read or write long intVal; // integer payload float fltVal; // floating payload char payLoad[32]; // string payload } Message; Message mes;
#ifdef DHT // DHT11 sensor ============================================ DHT dht(DHTPIN, DHTTYPE, 3); // initialise temp/humidity sensor for 3.3 Volt arduino #endif
#ifdef PIR // PIR sensor ================================================ #define PIRdelay delay(2000) // give the grid time to stabilize for the PIR, otherwise false triggers may occur after a send due to power dip (up to 2s?) int PirInput = 5; // PIR pin int calibrationTime = 20; //the time we give the sensor to calibrate (10-60 secs according to the datasheet) #endif
RFM69 radio;
//===================== SETUP ======================================== void setup() { #ifdef DEBUG Serial.begin(SERIAL_BAUD); #endif pinMode(ACT1, OUTPUT); // set actuator 1 ACT1State = 0; digitalWrite(ACT1, ACT1State); #ifdef DHT dht.begin(); // initialise temp/hum sensor #endif radio.initialize(FREQUENCY,NODEID,NETWORKID); // initialise radio #ifdef IS_RFM69HW radio.setHighPower(); // only for RFM69HW! #endif radio.encrypt(ENCRYPTKEY); // set radio encryption radio.promiscuous(promiscuousMode); // only listen to closed network wakeUp = true; // send wakeup message #ifdef DEBUG Serial.print("Node Software Version "); Serial.println(VERSION); Serial.print("\nTransmitting at "); Serial.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); Serial.println(" Mhz..."); #endif #ifdef PIR lastPIR = millis(); Serial.print("calibrating PIR sensor "); for(int i = 0; i < calibrationTime; i++){ Serial.print("."); delay(1000); } Serial.println("PIR sensor ACTIVE"); delay(50); #endif } // end setup
//==================== MAIN ======================================== void loop() {
/* DETECT INPUT CHANGE */ #ifdef PIR //////////////////////// PIRdelay; // give the grid time to stabilize for the PIR, otherwise false triggers occur after an RFM send/rcv (might need 2s) msgBlock = ((millis() - lastPIR) < HOLDOFF); // hold-off time for additional PIR messages 2s curPIRState = digitalRead(PirInput); // read PIR digital pin #ifdef DEBUG Serial.print("curPIRState: ");Serial.print(curPIRState);Serial.print(" millis: ");Serial.println(millis()); #endif if (!msgBlock && (curPIRState == 1)) { // presence detected? delay(5); lastPIR = millis(); // take timestamp send41 = true; // set PIR message flag } #endif //PIR////////////////////////
#ifdef BUTTON ////////////////////// curState = digitalRead(BTN); msgBlock = ((millis() - lastBtnPress) < HOLDOFF); // hold-off time for additional button messages if (!msgBlock && (curState != lastState)) { // input changed ? delay(5); lastBtnPress = millis(); // take timestamp send40 = true; // set button message flag if (curState == LOW) { if (toggleOnButton) { // button in toggle state ? ACT1State = !ACT1State; // toggle output digitalWrite(ACT1, ACT1State); } else if (TIMinterval > 0 && !timerOnButton) { // button in timer state ? timerOnButton = true; // start timer interval ACT1State = HIGH; // switch on ACT1 digitalWrite(ACT1, ACT1State); } } lastState = curState; } // TIMER CHECK // if (TIMinterval > 0 && timerOnButton) // =0 means no timer { if ( millis() - lastBtnPress > TIMinterval*1000) { // timer expired ? timerOnButton = false; // then end timer interval ACT1State = LOW; // and switch off Actuator digitalWrite(ACT1, ACT1State); } } #endif //Button///////////////////////
/* UPTIME */ if (lastMinute != (millis()/60000)) { // another minute passed ? lastMinute = millis()/60000; upTime++; }
/* PERIODIC TRANSMISSION */ if (TXinterval > 0) { int currPeriod = millis()/(TXinterval*1000); if (currPeriod != lastPeriod) { // interval elapsed ? lastPeriod = currPeriod; // list of sensordata to be sent periodically.. remove comment to include parameter in transmission/////////////////////////////////////// which inputs to send ///////////////// send0 = true; // send uptime send1 = true; // send transmission interval send2 = true; // signal strength send4 = true; // voltage level //send16 = true; // actuator state //send48 = true; // send temperature //send49 = true; // send humidity } }
/* SEND RADIO PACKETS */ sendMsg(); // send any radio messages
/* RECEIVE radio input */ if (receiveData()) parseCmd(); // receive and parse any radio input
} // end MAIN loop
//===================== FUNCTIONS ==========================================
/*======== RECEIVEDATA : receive data from gateway over radio */ // bool receiveData() { bool validPacket = false; if (radio.receiveDone()) // check for received packets { if (radio.DATALEN != sizeof(mes)) // wrong message size means trouble #ifdef DEBUG Serial.println("invalid message structure..") #endif ; else { mes = *(Message*)radio.DATA; validPacket = true; // YES, we have a packet ! signalStrength = radio.RSSI; #ifdef DEBUG Serial.print(mes.devID); Serial.print(", "); Serial.print(mes.cmd); Serial.print(", "); Serial.print(mes.intVal); Serial.print(", "); Serial.print(mes.fltVal); Serial.print(", RSSI= "); Serial.println(radio.RSSI); Serial.print("Node: "); Serial.println(mes.nodeID); #endif } } if (radio.ACKRequested()) radio.sendACK(); // respond to any ACK request return validPacket; // return code indicates packet received } // end recieveData
/*============== PARSECMD: analyse messages and execute commands received from gateway */ // void parseCmd() { // parse messages received from the gateway send0 = false; // initialise all send triggers send1 = false; send2 = false; send3 = false; send4 = false; send5 = false; send6 = false; send7 = false; send16 = false; send40 = false; send41 = false; send48 = false; send49 = false; send92 = false; switch (mes.devID) // devID indicates device (sensor) type { case (0): // uptime if (mes.cmd == 1) send0 = true; break; case (1): // polling interval in seconds if (mes.cmd == 0) { // cmd == 0 means write a value TXinterval = mes.intVal; // change interval to radio packet value if (TXinterval <10 && TXinterval !=0) TXinterval = 10; // minimum interval is 10 seconds if (setAck) send1 = true; // send message if required #ifdef DEBUG Serial.print("Setting interval to "); Serial.print(TXinterval); Serial.println(" seconds"); #endif } else send1 = true; // cmd == 1 is a read request, so send polling interval break; case (2): // signal strength if (mes.cmd == 1) send2 = true; break; case (3): // software version if (mes.cmd == 1) send3 = true; break; case (4): // battery level if (mes.cmd == 1) send4 = true; break; case (5): // set ack status if (mes.cmd == 0) { if (mes.intVal == 0) setAck = false; if (mes.intVal == 1) setAck = true; if (setAck) send5 = true; // acknowledge message ? } else send5 = true; // read request means schedule a message break; case (6): // set toggle if (mes.cmd == 0) { if (mes.intVal == 0) toggleOnButton = false; if (mes.intVal == 1) toggleOnButton = true; if (setAck) send6 = true; // acknowledge message ? } else send6 = true; break; case (7): // timer interval in seconds if (mes.cmd == 0) { // cmd == 0 means write a value TIMinterval = mes.intVal; // change interval if (TIMinterval <5 && TIMinterval !=0) TIMinterval = 5; if (setAck) send7 = true; // acknowledge message ? } // cmd == 1 means read a value else send7 = true; // send timing interval break; case (16): // Actuator 1 if (mes.cmd == 0) { // cmd == 0 means write if(mes.intVal == 0 || mes.intVal == 1) { ACT1State = mes.intVal; digitalWrite(ACT1, ACT1State); if (setAck) send16 = true; // acknowledge message ? #ifdef DEBUG Serial.print("Set LED to "); Serial.println(ACT1State); #endif }} else send16 = true; // cmd == 1 means read break; case (40): // binary input if (mes.cmd == 1) send40 = true; break; case (41): // PIR binary input if (mes.cmd == 1) send41 = true; break; case (48): // temperature if (mes.cmd == 1) send48 = true; break; case (49): // humidity if (mes.cmd == 1) send49 = true; break; default: send92 = true; // no valid device parsed } } // end parseCmd
//====================== SENDMSG: sends messages that are flagged for transmission // void sendMsg() { // prepares values to be transmitted bool tx = false; // transmission flag mes.nodeID=NODEID; mes.intVal = 0; mes.fltVal = 0; mes.cmd = 0; // '0' means no action needed in gateway int i; for ( i = 0; i < sizeof(VERSION); i++){ mes.payLoad[i] = VERSION[i]; } mes.payLoad[i] = '\0'; // software version in payload string if (wakeUp) { // send wakeUp call mes.devID = 99; wakeUp = false; // reset transmission flag for this message txRadio(); // transmit } if (send0) { mes.devID = 0; mes.intVal = upTime; // minutes uptime send0 = false; txRadio(); } if (send1) { // transmission interval mes.devID = 1; mes.intVal = TXinterval; // seconds (integer) send1 = false; txRadio(); } if (send2) { mes.devID = 2; mes.intVal = signalStrength; // signal strength (integer) send2 = false; txRadio(); } if (send3) { // node software version (string) mes.devID = 3; // already stored in payload string send3 = false; txRadio(); } if (send4) { // measure voltage.. mes.devID = 4; long result; // Read 1.1V reference against AVcc ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Convert while (bit_is_set(ADCSRA,ADSC)); result = ADCL; result |= ADCH<<8; result = 1126400L / result; // Back-calculate in mV mes.fltVal = float(result/1000.0); // Voltage in Volt (float) txRadio(); send4 = false; } if (send5) { // Acknowledge on 'SET' mes.devID = 5; if (setAck) mes.intVal = 1; else mes.intVal = 0;// state (integer) send5 = false; txRadio(); } if (send6) { // Toggle on Buttonpress mes.devID = 6; if (toggleOnButton) mes.intVal = 1; // read state of toggle flag else mes.intVal = 0; // state (integer) send6 = false; txRadio(); } if (send7) { // timer interval mes.devID = 7; mes.intVal = TIMinterval; // seconds (integer) send7 = false; txRadio(); } if (send16) { // state of Actuator 1 mes.devID = 16; mes.intVal = ACT1State; // state (integer) send16 = false; txRadio(); } if (send40) { // Binary input read mes.devID = 40; if (curState == LOW) mes.intVal = 1; // state (integer) send40 = false; txRadio(); } if (send41) { // PIR Binary input read mes.devID = 41; if (curPIRState == HIGH) mes.intVal = 1; // state (integer) 1 for ON send41 = false; txRadio(); } if (send48) { // Temperature mes.devID = 48; #ifdef DHT temp = dht.readTemperature(); #endif mes.fltVal = temp; // Degrees Celcius (float) send48 = false; txRadio(); } if (send49) { // Humidity mes.devID = 49; #ifdef DHT hum = dht.readHumidity(); #endif mes.fltVal = hum; // Percentage (float) send49 = false; txRadio(); } if (send92) { // error message invalid device mes.intVal = mes.devID; mes.devID = 92; send92 = false; txRadio(); } }
/*======================= TXRADIO */ // void txRadio() // Transmits the 'mes'-struct to the gateway { if (radio.sendWithRetry(GATEWAYID, (const void*)(&mes), sizeof(mes))) #ifdef DEBUG {Serial.print("Node: "); Serial.print(mes.nodeID); Serial.print(" device: "); Serial.print(mes.devID); Serial.print(" cmd: "); Serial.print(mes.cmd); Serial.print(" val: "); Serial.print(mes.intVal); Serial.print(" val: "); Serial.print(mes.fltVal); Serial.print(" RSSI: "); Serial.println(radio.RSSI);} else Serial.println("No connection...") #endif ;} // end txRadio
|
|
|
Post by ionized on Aug 10, 2015 23:19:26 GMT
Tryed to compile your PIR sketch but have many errors .Do you have a sketch that will compile?
|
|