Getting state change value from analogRead()

Hello everyone, I have been stuck on this problem since sometime. So basically, I just need a state change detection of analogRead(). Its working fine with the "ON" part. But it keeps going on when the switch is in "OFF" state. Here is my code:

char switchPin                     = A1;
const unsigned long switchReadTime = 50;
const unsigned long debounceTime   = 50;
unsigned long lastDebounceTime     = 0;
unsigned long previousTime         = 0;
int switchValue                    = 0;
int switchState                    = 0;
int lastSwitchState                = 0;

void setup() {
  Serial.begin(9600);
  pinMode(switchPin, INPUT);
}

void loop() {
  unsigned long currentTime = millis();

  if (currentTime - previousTime >= switchReadTime) {
    for (int i = 0; i < 10; i++) {
      switchValue += analogRead(switchPin);      
    }
    switchValue = switchValue / 10;
    switchState = switchValue;
    previousTime = currentTime;
  }
  if (currentTime - lastDebounceTime >= debounceTime) {
    if (switchState != lastSwitchState) {
      if (switchState == 1136) {
      Serial.println("ON");
      lastSwitchState = switchState;
      lastDebounceTime = currentTime;
      } else {
        Serial.println("OFF");
        lastSwitchState = switchState;
        lastDebounceTime = currentTime;
      }
    }
  }
}

Thank you in advance.. :slight_smile:

You should reset switchValue before this for loop.

Usually analogRead has a maximum value of 1023... what device are you using?

At starts I have put switchValue = 0;
Shall I reset switchValue at the end of the loop?

So I was getting 1023 before doing an average of the analog value. But after I averaged it, it was showing 1136 for some reason. I am using a normal switch from home.

Hello nishantd2007

What are the analog limit values to switch ON and OFF?

Have a nice day and enjoy programming in C++ and learning.
MIND THE GAP

For ON - its 1136 and for OFF its less than 1136

Strange. Usually a state change detection of an analog value requires that you first define a detection "window" so that ADC noise isn't detected as a change.

I posted before the last reply.

Logic would be:

if ON
{
if reading < 1136
  {
   OFF
   }
}
else
{
  if reading >= 1136
  {
  ON
  }
}

I bet that will be a typical XY problem.

2 Likes

For the window I used the millis() debounce. So if the value changes in the debounce time its not counted.

What does that mean, exactly? A domestic light switch? Please post a photo.

Why are you using analogRead() with a switch? A switch is a digital device, you should be using digitalRead().

Please tell us what kind of arduino you are using. With typical Arduino like Uno, Mega, there is no way for your average reading to exceed 1023.

1 Like

The requirement as you expressed it, does not need any timing at all. The logic in reply #6 will work reliably no matter when the samples are taken. If you need hyteresis, just change one limit:

if ON
{
if reading < 1136
  {
  OFF
  }
}
else
{
  if reading >= 1136 + hysteresis value
  {
  ON
  }
}

I am using Arduino UNO at 5V, maybe there was a glitch with the output, I was getting 1136, but now I am receiving 1023 as output.

Actually there is alot of noice in the output, I had to filter it out using millis() which is working like a charm. Now I am getting constant output of the switch which is either ON or OFF. But I need just the change of state detection.

Its working fine when the switch is in ON position, like the output stops at on, but it keeps printing on OFF position. I just want the one output of OFF and wait for the switch to turn on.

We usually recommend placing a 10k from an analog pin to GND, for noise suppression add a 100nF ceramic capacitor in parallel with this resistance.


Always show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.

Why do you average the analogue voltage?
What is this mean value needed for?
Isn't a two-point control better suited here?

The noise suppression is not so much of an issue than getting the state change. But to answer your question, I am connecting it directly from the switch to the board. Without using any resistor or capacitor. I want the circuit connected directly for my current project.

Please show us a schematic of your circuit.

Also show us a good image of your actual wiring.

I am averaging the values for getting a stable output from the switch. These value are then used to determine the ON and OFF state of the switch. Due to this method, I don't need to attach any additional electronics to filter out the noise.

How do you/we know if additional electronics needs to be added.


Maybe your input signal has dangerous voltage spikes on it, we need more information.


Last time:

Please show us a schematic of your circuit.

Also show us a good image of your actual wiring.

The Arduino is connected to Raspberry Pi 4

Thank you.


Wire you switch as S3 in the schematic below.

The switch will read a LOW when it is closed.


1 Like