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? 🙂


  • Mod

    Are relays opto isolated?



  • @gohan said in Noisy inputs..:

    Are relays opto isolated?

    Yes.


  • Mod

    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.


  • Mod

    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.


 

277
Online

7.7k
Users

8.6k
Topics

92.3k
Posts