ESP32 - reed switch for counting

Hello everyone,
I am new to the forum and to the ESP32s' world. I am trying to do a home project with a few sensors. One of the things that I want to achieve is to use a reed switch to count number of rotations of a wheel. It does a full round for more than 0.5s. My idea is to use a stationary reed switch and a magnet on the wheel. When the magnet goes near the switch, I count it. Every few seconds I print the counter.
Here is my code:

unsigned long reedCount;
unsigned long previousMillisReed = 0; 
const long reedInterval = 3000; //3 seconds
const int reedSwitch = 4;

IRAM_ATTR void changeReedStatus() {
  reedCount++;
}

void setup() {
  Serial.begin(9600);
  pinMode(reedSwitch, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(reedSwitch), changeReedStatus, HIGH);
}

void loop() {
  //Reed switch
  reedSwitchFunc();
}

void reedSwitchFunc() {
    unsigned long currentMillisReed = millis();
    if(currentMillisReed - previousMillisReed >= reedInterval) {
      Serial.println(reedCount);
      previousMillisReed = currentMillisReed;
    }
}

and my schema:

The problem is that more than 25% of the rotation cycles are not counted. What am I doing wrong? Thanks in advance!

Welcome to the forum. I hope your user name ages badly. :expressionless:

The variable reedCount is used in an ISR and in non-interrupt code.

You must add the qualifier volatile to the declaration, viz:

volatile unsigned long reedCount;

Also, any non-interrupt use must be done with interrupts off as the variabke is multiple bytes. Most ppl just make a copy:

  unsigned long myCopy;

  noInterrupts();
  myCopy = reedCount;
  interrupts();

and use only the copy subsequently.

You may have other issues, but those two details cannot be overlooked.

a7

1 Like
  • Reed switches are notorious for bouncing, might be the worst switch ever.

  • Consider using a digital Hall Effect Sensor.

  • Suggest you simply use a 30-50ms polling scheme (looking for a change in state) instead of using interrupts.

2 Likes

You can also simplify your schematic. Since you are using INPUT_PULLUP, remove the external resistor and connect the other side of the reed switch to ground, not VCC. The pin will remain high until the magnet closes the reed switch and pulls it low

1 Like

use Hall effect switch activated by a magnet as recommended by @LarryD - should give a clean signal with no bounce
also consider using the ESP32 Pulse Counter (PCNT) hardware

1 Like

It is an ESP32, so an operation on a 32 bit variable will be atomic (unless it is in a packed structure). Still a good idea - you never know where code may end up.

3 Likes

A reed switch can be unreliable for counting rotations due to mechanical wear, slow response time, and bouncing issues, leading to missed counts. A better alternative is a Hall Effect Sensor (like A3144), which works with a magnet like a reed switch but is fully electronic, faster, and more reliable. If higher accuracy is needed, an optical sensor (like an IR obstacle sensor) or a rotary encoder can provide more precise tracking. A Hall Effect Sensor should work perfectly as a direct replacement in your setup.

1 Like