Noisy inputs..
-
Hi all,
I built a gate controller for myself (https://www.openhardware.io/view/458/Gate-Controller). The relay pins are wrong (N/O and N/C) but that is not relevant here.The issue is that when I stop or start the relays when AC is connected my inputs trigger changes. This does not happen when I disconnect the AC. The relays are driving gate motors using starter capacitors.
#include "PinChangeInterrupt.h" #define TINY_GSM_MODEM_A6 #define RF69_IRQ_NUM 2 #define MY_NODE_ID 2 #define MY_DEBUG #define MY_RADIO_RFM69 #define MY_RFM69_FREQUENCY RF69_868MHZ #include <SPI.h> #include <MySensors.h> #include <TinyGsmClient.h> #define SerialAT Serial1 #define DELAY 2000 /////////////////// Gates /////////////////////// #define RGC 14 #define LGO 15 #define RGO 12 #define LGC 18 //////////////////// Buttons /////////////////// #define KEYPAD 20 #define INTERCOM 19 #define PHOTOCELLS 23 #define KEYFOB 21 #define WALLSWITCH A7 #define REEDSWITCH 22 TinyGsm modem(SerialAT); MyMessage msg(1,V_TRIPPED); MyMessage msg2(2,V_TEXT); unsigned long const gatesTimeOpenClose = 29000; unsigned long const gatesStayOpen = 80000; unsigned long movingTime = 0, openTime = 0; volatile bool keyPad = false, interCom = false, keyFob = false; bool gatesOpening = false, gatesClosing = false, gatesOpen = false, stringComplete = false, domoTrigger = false; String inputString = ""; String reason = ""; int oldsec=0; volatile bool startup = true, changeDetected = false; void openGates() { if (gatesOpening) { return; } if (gatesClosing) { unsigned long temp = millis() - movingTime; // temp is ms since gate was closing movingTime = millis() - (gatesTimeOpenClose - temp) + 1000; values(); Serial.print("OpenGates() :: Reopening:"); Serial.println(temp/1000); stopGates(); } else { movingTime = millis(); } if (gatesOpen) { // Reset open timer openTime = millis(); values(); Serial.println("OpenGates() : Resetting open timer"); return; } gatesOpening = true; send(msg2.set(reason.c_str())); reason=""; send(msg.set(0)); digitalWrite(RGO,LOW); values(); Serial.println("OpenGates() : Right"); delay(2000); digitalWrite(LGO,LOW); values(); Serial.println("OpenGates : Left"); } void stopGates() { digitalWrite(LGC,HIGH); digitalWrite(LGO,HIGH); values(); Serial.println("StopGates : Stopping Left gate"); if (gatesClosing) { delay(1000); } digitalWrite(RGC,HIGH); digitalWrite(RGO,HIGH); Serial.println("StopGates : Stopping Right gate"); gatesOpen = gatesOpening?true:false; if (gatesOpen) { values(); Serial.println("StopGates() : Gates are open"); openTime = millis(); } gatesOpening = false; gatesClosing = false; } void closeGates() { while(analogRead(WALLSWITCH) < 615) { unsigned long wallOpen = millis(); if(millis() % 10000 == 0) { int sec = (millis() - wallOpen)/1000; if (sec != oldsec) { values(); Serial.print("CloseGates() : Wall switch: "); Serial.print(sec); Serial.println('s'); oldsec = sec; } } } if (gatesClosing) { return; } movingTime = millis(); gatesClosing = true; gatesOpen = false; values(); keyPad = false, interCom = false, keyFob = false; Serial.println("CloseGates() : Closing Left gate"); digitalWrite(LGC,LOW); values(); delay(2000); Serial.println("CloseGates() : Closing Right gate"); digitalWrite(RGC,LOW); values(); } void CheckGates() { if (gatesOpening || gatesClosing) { if((millis() - movingTime) > gatesTimeOpenClose) { stopGates(); } else { if (millis() % 2000 == 0) { values(); int secs = (millis() - movingTime) / 1000; if (secs != oldsec) { if (gatesOpening) { Serial.print("CheckGates() : Opening:"); } else { Serial.print("CheckGates() : Closing:"); } Serial.print((movingTime + gatesTimeOpenClose - millis()) / 1000); Serial.println("s"); oldsec = secs; } } } } if (gatesClosing) { if (digitalRead(PHOTOCELLS) == HIGH) { Serial.println("CheckGates() : Photocells tripped - Reopening"); openGates(); } if (digitalRead(REEDSWITCH) == LOW) { Serial.println("CheckGates() : ReedSwitch tripped"); send(msg.set(1)); stopGates(); } } if (gatesOpen) { if((millis() - openTime) > gatesStayOpen) { closeGates(); } else { if (millis() % 5000 == 0) { int secs = (millis() - openTime) / 1000; if (secs != oldsec) { values(); Serial.print("CheckGates() : Open "); Serial.print(secs); Serial.print("s :: "); Serial.print((openTime + gatesStayOpen - millis()) / 1000); Serial.println("s"); oldsec = secs; } } } } } void setup() { Serial.println("Setup() : Gate sketch started"); inputString.reserve(200); SerialAT.begin(115200); delay(5000); // Give modem a chance. Serial.print("Setup() : Initialising Modem..."); while(!modem.init()) { Serial.println("Setup() : ERR: Modem init"); delay(10000); } Serial.println("Setup() : Waiting for network.."); while(!modem.waitForNetwork()) { Serial.println("Setup() : ERR: GSM network"); delay(10000); } Serial.println("Setup() : Modem ready"); SerialAT.write("AT+CLIP=1\r\n"); pinMode(WALLSWITCH, INPUT); pinMode(INTERCOM, INPUT_PULLUP); pinMode(KEYPAD, INPUT_PULLUP); pinMode(KEYFOB, INPUT_PULLUP); pinMode(REEDSWITCH, INPUT_PULLUP); pinMode(PHOTOCELLS, INPUT_PULLUP); attachPCINT(digitalPinToPCINT(INTERCOM), PBChangeIntercom, CHANGE); attachPCINT(digitalPinToPCINT(KEYFOB), PBChangeKeyFob, CHANGE); attachPCINT(digitalPinToPCINT(KEYPAD), PBChangeKeyPad, CHANGE); int gatePins[4] = {LGO,LGC, RGO, RGC}; for (int x=0;x<4;x++) { pinMode(gatePins[x],OUTPUT); digitalWrite(gatePins[x],HIGH); } gatesOpen = (digitalRead(REEDSWITCH))==LOW?false:true; if (gatesOpen) { Serial.println("Setup() : Gates are open on startup"); closeGates(); } values(); startup = false; } void loop() { if (changeDetected) { Serial.println("Change detected"); changeDetected = false; } if (keyFob) { values(); Serial.println("loop() : Gate open request detected by Key Fob"); reason="Opened by Key Fob"; openGates(); keyFob = false; } if (interCom) { values(); Serial.println("loop() : Gate open request detected by Intercom"); reason="Opened by Intercom"; openGates(); interCom = false; } if (keyPad) { values(); Serial.println("loop() : Gate open request detected by key pad"); reason="Opened by Key Pad"; openGates(); keyPad = false; } if (stringComplete) { inputString.trim(); if (inputString.length() > 0) { Serial.print("loop() : GSM:"); Serial.println(inputString); } if(inputString.indexOf("1111111111") > 0 || inputString.indexOf("222222222222") > 0 || inputString.indexOf("333333333333") > 0) { String phoneNum = inputString.substring(inputString.indexOf("087"),inputString.indexOf("087")+10); Serial.print("loop() : GSM:"); Serial.print(phoneNum); Serial.println(" CALL"); SerialAT.write("ATH \n\r"); reason="Opened by " + phoneNum; openGates(); } // clear the string: inputString = ""; stringComplete = false; } CheckGates(); reason = ""; } void receive(const MyMessage &message) { if (message.type == V_STATUS && message.sensor == 1) { if (atoi(message.data) == 0) { Serial.println("receive() : Open req from domo"); reason = "Opened from domoticz"; openGates(); } } } void serialEvent1() { while (SerialAT.available()) { char inChar = (char)SerialAT.read(); inputString += inChar; if (inChar == '\n') { stringComplete = true; } } } void values() { Serial.print("KF: "); Serial.print(keyFob); Serial.print("| KP: "); Serial.print(keyPad); Serial.print("| IN: "); Serial.println(interCom); } void presentation() { sendSketchInfo("Front Gates", "3.4"); present(1, S_DOOR, "Front Gates"); present(2, S_INFO, "Gate Open Reason"); } void PBChangeIntercom() { if (startup) return; volatile static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); if (interrupt_time - last_interrupt_time > 1000) interCom = true; last_interrupt_time = interrupt_time; changeDetected = true; } void PBChangeKeyPad() { if (startup) return; volatile static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); if (interrupt_time - last_interrupt_time > 1000) keyPad = true; last_interrupt_time = interrupt_time; changeDetected = true; } void PBChangeKeyFob() { if (startup) return; volatile static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); if (interrupt_time - last_interrupt_time > 1000) keyFob = true; last_interrupt_time = interrupt_time; changeDetected = true; }
The code is a bit verbose as I added some debug and extra vars to help me see what was going on. The inputs are:
Photocells : laser sensor that detects when laser path is broken.
Wallswitch: Switch inside house to keep gates open. Connected to analog A7 and gnd with a connection from A7 to +5 via a 220 resistor.
Intercom: Momentary switch in house to open gates.
Reed: A reed switch that triggers when the gates connect on close.
KeyFob: A Keyfob
KeyPad: Keypad switch.
Phone: A6 module.The motors pull about 1.9 A IIRC. Do I need LPFs? Any other ideas?
Thanks!
-
Bump?
-
Are relays opto isolated?
-
-
did you try to power the relay with a separate power supply to totally isolate the arduino from the relays circuit?
-
No. I can try that but because I have already received the PCBs I would need to hack it a bit. It is worth mentioning that this does not happen when AC is not passed through the relays but relays are still connected.
-
That's why optocoupler are used, but also isolating the rest it could be beneficial as most of the relay boards allow it for a reason
-
I'm gonna see if I can grab a few ferrite cores and stick then on the AC lines to see if that suppresses the EMI.