A3144 Hall Effect sensors issues

Hello

I'm currently working on a garage door security project.
The goal is to watch latches and lock, make sure everything stays closed, and push states changes to mqtt.

I'm using A3144 hall sensor and strong magnet with a typical d1mini implentation - see image - (not using decoupling capacitor, maybe an issue..)
A3144_1-500x500

The software mainly consists of 3 interrupts watching state changes.

Two issues I've noticed so far :

  • Although there's no magnet movement, sensors outputs could toggle for no reason (quite sure this could be a capacitor issue as read elsewhere)
  • Last time I've tried the setup for a long time, the d1 mini esp seems to have crashed. I'm suspecting something is wrong with my code.

Anyways I'm receiving mqtt updates but it's not reliable..

Any suggestions ?

Thanks for reading me.

my code below :

#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

const int pinSensorSA = D1;
const int pinSensorSB = D2;
const int pinSensorSL = D5;

#define WLAN_SSID       "ssid"
#define WLAN_PASS       "pass"
#define AIO_SERVER      "pi-ha.retz.lan"
#define AIO_SERVERPORT  1883
#define AIO_USERNAME    "mqtt"
#define AIO_KEY         "pass"

WiFiClient client;

Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish pushSA = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/retz/atelier/door/side_a");
Adafruit_MQTT_Publish pushSB = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/retz/atelier/door/side_b");
Adafruit_MQTT_Publish pushSL = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/retz/atelier/door/lock");
Adafruit_MQTT_Publish pushStatus = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/retz/atelier/door/status");

volatile byte stateSA = HIGH;
volatile byte stateSB = HIGH;
volatile byte stateSL = HIGH;

void MQTT_connect();

const long interval = 5000; 
unsigned long previousMillis = 0;

void ICACHE_RAM_ATTR onChangeSL() {
  stateSL = !stateSL;
  if(stateSL) {
    Serial.println(F("SL Open"));
    pushSL.publish("open");
  } else {
    Serial.println(F("SL Closed"));
    pushSL.publish("closed");
  }
}

void ICACHE_RAM_ATTR onChangeSA() {
  stateSA = !stateSA;
  if(stateSA) {
    Serial.println(F("SA Open"));
    pushSA.publish("open");
  } else {
    Serial.println(F("SA Closed"));
    pushSA.publish("closed");
  }
}

void ICACHE_RAM_ATTR onChangeSB() {
  stateSB = !stateSB;
  if(stateSB) {
    Serial.println(F("SB Open"));
    pushSB.publish("open");
  } else {
    Serial.println(F("SB Closed"));
    pushSB.publish("closed");
  }
}

void setup() {
  Serial.begin(115200,SERIAL_8N1,SERIAL_TX_ONLY);

  pinMode(pinSensorSA, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinSensorSA), onChangeSA, CHANGE);
  pinMode(pinSensorSB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinSensorSB), onChangeSB, CHANGE);
  pinMode(pinSensorSL, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinSensorSL), onChangeSL, CHANGE);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  MQTT_connect();
  pushStatus.publish("started");
}

void loop() {
  MQTT_connect();
  
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    pushStatus.publish("update");

    if(stateSA) {
      pushSA.publish("open");
    } else {
      pushSA.publish("closed");
    }

    if(stateSB) {
      pushSB.publish("open");
    } else {
      pushSB.publish("closed");
    }

    if(stateSL) {
      pushSL.publish("open");
    } else {
      pushSL.publish("closed");
    }
  }  
}

void MQTT_connect() {
  int8_t ret;

  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}

-> My sensors are quite far from the board (1 meter). Do I need to place the capacitor next to the board ? Or next to the sensor ?
-> Does my interrupts implementation could be a source of crash ?

  • Don’t use interrupts, pole them instead.
1 Like

The 0.1uF caps at the switch (sensor) end may help to dump noise to ground and stabilize the sensor. I use the caps as a matter of course. Every HAll switch gets a cap.

Also lowering the value of the pull up resistor help (stronger pull up).

1 Like

Still, please share a schematic of the entire project and photos of how it was built. Issues like stability may have to do with wiring, layout etc.

Your Hall sensor may respond to other magnetic fields as well. Strong currents in nearby wires (e.g. power tools) can qualify. Lightning nearby as well.

As hinted above, no need to use interrupts. The fact that you use Serial.print inside an ISR makes matters worse. This is exacerbated by the lack of any debounce on your sensor, meaning the ISR may trigger several times within a few milliseconds, and that may result in Serial/UART buffer issues due to nested interrupts.

But hardware issues can also contribute to the stability problem; see initial remark above.

I noticed in the datasheet page 2, the typical hysteresis value (difference between ON and OFF) is not defined for the A3144. That may be a factor in your problem.

https://www.mpja.com/download/a3144eul.pdf

Hello

Thanks a lot for your answers

My next actions will be to remove interrupts in code and adding capacitors.
Also serial communication when not testing.

Not sure to understand the potential hysteresis problem..

Here's my schematic
(resistors are 10k)

Also some pictures

Breadboard setup (haven't created a PCB so far..)

One of the side sensor

Also the magnet on the floor (side sensor magnet)

Hysteresis means that the turn on and turn off setpoint values are different. This prevents " chatter" around the setpoint.

Here is a short demo that shows the use of hysteresis.

const byte ldrInPin = A0;

int ldrValue;
int ldrThreshold = 500;
int hysteresis = 50;

void setup()
{
   Serial.begin(115200);
   pinMode(ldrInPin, INPUT_PULLUP);
}

void loop()
{
   static unsigned long timer = 0;
   unsigned long lnterval = 250;
   if (millis() - timer >= lnterval)
   {
      timer = millis();
      ldrValue = analogRead(ldrInPin);
      Serial.println(ldrValue);
      if(ldrValue > ldrThreshold + hysteresis)
      {
        Serial.println("It is dark");
      }
      else if (ldrValue < ldrThreshold - hysteresis)
      {
        Serial.println("It is not dark");
      }
   }

}const byte ldrInPin = A0;

int ldrValue;
int ldrThreshold = 500;
int hysteresis = 50;

void setup()
{
   Serial.begin(115200);
   pinMode(ldrInPin, INPUT_PULLUP);
}

void loop()
{
   static unsigned long timer = 0;
   unsigned long lnterval = 250;
   if (millis() - timer >= lnterval)
   {
      timer = millis();
      ldrValue = analogRead(ldrInPin);
      Serial.println(ldrValue);
      if(ldrValue > ldrThreshold + hysteresis)
      {
        Serial.println("It is dark");
      }
      else if (ldrValue < ldrThreshold - hysteresis)
      {
        Serial.println("It is not dark");
      }
   }

}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.