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.


Log in to reply
 

Suggested Topics

24
Online

11.2k
Users

11.1k
Topics

112.5k
Posts