|
Post by chrisinkc on Mar 10, 2016 4:30:47 GMT
Has anybody run into the issue of a SSR firing multiple times instead of just once?
I am using Papa's schematics from his Sep 18th, 2015 post for the garage door node. I have 2 garage doors so I have 2 SSRs on separate nodes. They both worked fine for a week or so. One of them still works fine, but when you press the virtual garage door button in opennhab for the other door, it acts as if the button has been pressed twice. The garage door goes up, then stops, then goes back down. If the garage door is all the way open and you press the button, the door will jerk down about 4 inches, stop, and then go back up. The real garage door openers work just fine. It seems like the SSR is firing off twice instead of just once. No changes have been made since I first installed the nodes.
Anybody else run into this issue? Is my SSR crapping out on me?
|
|
|
Post by papa on Mar 10, 2016 12:01:25 GMT
Chris, I'm not sure why things would change with your SSRs.
When you were tweaking things to get the email notification working, are you sure you did not change a little something related to the now problematic door opener?
You might try some hardware swaps to narrow down where the malfunction is. Swap SSRs between nodes. Swap nodes between doors. That might help suggest if it is hardware (SSR, opener?) or software (node, OpenHAB configs?)
Are hardware, wiring, & node sketches (except node id) exactly the same for both opener nodes?
For OpenHAB virtual push buttons for both doors are you using items similar to the following ?? // On OpenHAB sitemap, will show a virtual switch for open / close garage door (with PushBtn icon) Switch Act_Node98 <PushBtn> {mqtt=">[mosquitto:home/rfm_gw/sb/node98/dev16:command:ON:ON],>[mosquitto:home/rfm_gw/sb/node98/dev16:command:OFF:OFF]", autoupdate="false"}
I tailored the garage door opener sketch to work with MY opener control board. It briefly pulses the DC output relay to simulate a button press at the wall or on a remote.
You might experiment with a different (shorter?) pulse ...
In the sketch, find the following lines that are a little after "case (16):" ...
digitalWrite(ACT1, 1); // BA: briefly turn output on then off if (setAck) send16 = true; // original acknowledge message ? delay(100); ^^ this delay controls how long the node pulses the SSR.
Also (I forget), is your node sending 5 volts (via a transistor) or 3.3 volts (directly from the digital pin)? I was able to trigger my DC to DC SSR with 3.3 volts.
|
|
|
Post by papa on Mar 10, 2016 14:00:29 GMT
You might upload your opener sketch. Perhaps some clue can be seen there.
The opener node sketch I posted Sep 18, 2015 at 1:55pm in the Success... thread (the first I adapted from computourist's) was pretty messy, a lot of trying stuff until something worked. Looking at it now, I see code where I was trying to keep the reed switch. We may need to remove more code not related to the SSR.
Likewise, for my opener node, I did not need to debounce the virtual push button switch on the OpenHAB user interface. However, in your opener node, you might need that code from the original DHT end node that ignored any additional button signals for 2 seconds.
|
|
|
Post by chrisinkc on Mar 10, 2016 20:22:35 GMT
Below is my sketch. The only thing this node is used for is the SSR. There are no other sensors, buttons, or relays being used.
#include <RFM69.h>
#include <SPI.h>
#include <DHT.h>
//
// CONFIGURATION PARAMETERS
//
#define NODEID 04 // unique node ID within the closed network [ 2-231 ??]
#define GATEWAYID 1 // node ID of the Gateway is always 1
#define NETWORKID 100 // network ID of the network
#define ENCRYPTKEY "xxxxxxxxxxxxxxxx" // YOU must set your 16-char encryption key; same as on Gateway!
#define DEBUG // uncomment for debugging
#define VERSION "DHT-V2.1 Garage Relay" // this value can be queried as device 3
// Wireless settings comment/ uncomment to 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 RFM69Hx! Leave out if you have RFM69W or like!
#define ACK_TIME 50 // max # of ms to wait for an ack
// DHT 11 / sensor setting
//#define DHTPIN 4 // DHT data connection
//#define DHTTYPE DHT11 // type of sensor
#define SWCH 7 // BA: pin for switch or jumper, usually pulled low via 10K ohms
#define ACT1 9 // Actuator pin (LED or relay)
#define BTN 8 // Button pin, normally pulled up hi (connected to power via 10K ohms
#define SERIAL_BAUD 115200
#define HOLDOFF 2000 // blocking period between button & switch messages
//
// STARTUP DEFAULTS
//
long TXinterval = 20; // periodic transmission interval in seconds
long TIMinterval = 20; // timer interval in seconds
bool ackButton = false; // flag for message on button press
bool toggleOnButton = false; // default = true, toggle output on button press
//
// VARIABLES
//
long lastPeriod = -1; // timestamp last transmission
long lastBtnPress = -1; // timestamp last buttonpress
long lastSwChng = -1; // BA timestamp last switch change
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; //no send8, which was dropped
bool send16, send40, send41, send48, send49, send92; // message triggers, BA added send41
bool promiscuousMode = false; // only listen to nodes within the closed network
bool curState = true; // current button state
bool lastState = true; // last button state
bool curSWCH = true ; // BA: current switch state
bool lastSWCH = true ; // BA: last switch state
bool wakeUp = true; // wakeup flag
bool timerOnButton = false; // timer output on button press
bool msgBlock = false; // flag to hold button messages to prevent overload
bool msgBlk2 = false; // BA: flag to hold switch 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;
RFM69 radio;
//
//===================== SETUP ========================================
//
void setup() {
#ifdef DEBUG
Serial.begin(SERIAL_BAUD);
#endif
pinMode(ACT1, OUTPUT); // set actuator 1
ACT1State = 0;
digitalWrite(ACT1, ACT1State); //BA: Start with LED / Relay off
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
// removed from node20: send8 = false; // removed initialise button press flag
#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
} // end setup
//
//
//==================== MAIN ========================================
//
void loop() {
// RECEIVE radio input
//
if (receiveData()) parseCmd(); // receive and parse any radio input
// 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
// send1 = true; // send transmission interval
send2 = true; // signal strength
send4 = true; // voltage level [including battery]
send16 = true; // actuator state [BA uncommented]
send41 = true; // BA added for switch state
}
}
// SEND RADIO PACKETS
//
sendMsg(); // send any radio messages
} // end 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; // BA added
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(8) gone from node 20
case (16): // BA reenabled: Actuator 1 message received
if (mes.cmd == 0) { // cmd == 0 means write
if(mes.intVal == 0 || mes.intVal == 1) {
ACT1State = mes.intVal;
// digitalWrite(ACT1, ACT1State); // original TOGGLE output
digitalWrite(ACT1, 1); // BA: briefly turn output on then off
if (setAck) send16 = true; // original acknowledge message ?
delay(100); // BA
digitalWrite(ACT1, 0); // BA
if (setAck) send16 = true; // BA moved above here
#ifdef DEBUG
Serial.println("Flashed LED/Relay"); // BA: was "Set LED to "
// Serial.println(ACT1State);
#endif
}}
else send16 = true; // cmd == 1 means read
break;
case (40): // button binary input
if (mes.cmd == 1) send40 = true;
break;
case (41): // BA added switch or jumper input
if (mes.cmd == 1) send41 = 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 = VERSION; }
//mes.payLoad = '\0'; // software version in payload string [ ?? 1]
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.. [incl battery level]
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 (send8) gone from node 20
if (send16) { // BA reenabled state of Actuator 1
mes.devID = 16;
mes.intVal = ACT1State; // state (integer)
send16 = false;
txRadio();
}
if (send40) { // Binary input read [not Button pressed]
mes.devID = 40;
if (curState == LOW) mes.intVal = 1; // state (integer) [new logic]
send40 = false;
txRadio();
}
if (send41) { // BA added Binary switch input read [not Button pressed]
mes.devID = 41;
if (curSWCH == LOW) mes.intVal = 1; // state (integer) [new logic]
send41 = 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(" message ");
Serial.print(mes.devID);
Serial.println(" sent...");}
else Serial.println("No connection...")
#endif
;} // end txRadio
|
|
|
Post by papa on Mar 10, 2016 20:45:59 GMT
OK, thanks for your copy of the opener sketch. I'll start looking through it.
When you get a chance, you could try / respond to what I wrote in the post above that starts, "Chris, I'm not sure why things would change with your SSRs. ..."
Among other things, I'd like to hear:
Did you try swapping parts between the opener nodes? Results?
For OpenHAB virtual push buttons for both doors are you using items similar to the following ?? // On OpenHAB sitemap, will show a virtual switch for open / close garage door (with PushBtn icon) Switch Act_Node98 <PushBtn> {mqtt=">[mosquitto:home/rfm_gw/sb/node98/dev16:command:ON:ON],>[mosquitto:home/rfm_gw/sb/node98/dev16:command:OFF:OFF]", autoupdate="false"}
|
|
|
Post by papa on Mar 10, 2016 23:29:10 GMT
Ok, I compared your opener sketch with my original adaptation & they are much the same, except for essential customizing like node id, encryption
Like I said, the sketch is a bit "messy." I see unnecessary code left from the DHT end node & other things I was trying to include in the node, but I'm not sure any of it would cause the SSR to trigger twice.
Again like I said ... When you get a chance, you could try / respond to what I wrote in the post above that starts, "Chris, I'm not sure why things would change with your SSRs. ..." Let's work thru those things first.
|
|