1

Hi I was wondering if a digitalRead state change detection could be saved in a variable like counter++, just like you can do with an interrupt function.

arent these two operations almost the same?

like have an external circuit with a reed closed by a magnet, to take the place of a momentary push button,

Jim
  • 31
  • 2
  • 2
  • 9

2 Answers2

1

The 2 techniques described in the question are commonly referred to as "polling" and "interrupt". Either will work. Polling is suggested for beginner programmers and when time is not important. Such as scanning an array of human controlled buttons. Whereas interrupts are usually reserved for when time is of the essence. Such as synchronizing a camera's release switch with a strobe flash.

Also, consider polling as a simple to understand, easy to test sequence of events that will always happen in the expected order. While interrupts can happen at any time and all interruptible code has to be written to tolerate being interrupted.

Often, debouncing is the more difficult problem when combining mechanical switches and microprocessors. A good fundamental exercise is to write your own debounce program. However, an Arduino debounce library is already available.

st2000
  • 7,343
  • 2
  • 11
  • 19
0

The fundamental difference between polling (digitalRead()) and interrupts is that of time. Yes, I know we discussed time and interrupts at length in another of your questions, but I'm not talking about recording time here.

With an interrupt you know (pretty much) when an input changed. With polling you can only know that it changed sometime in the past. An interrupt occurs at the moment an input changes state (what that change is depends on the type of interrupt). That makes it possible for your program to remember that time (by querying millis() for example).

With digitalRead() the only way you can know if an input has changed state is if you manually remember what the old state was and compare it, so all you can know is that it's changed since last time you examined the input, and if those times are far apart all you can say is "sometime in the past X milliseconds it changed state".

If your input changes faster than that polling time you won't know about it. For instance, if you end up polling every 10 milliseconds, and you have a pulse on your input pin that lasts 4 milliseconds (that's an eternity in microcontroller time) but occurs part way between two polls (say from 3ms to 7ms) you'll never see it.

To put it more formally, to detect a signal of frequency f Hz you have to sample the input at minimum 2f Hz (or a period of 1/(2f) seconds. This is known as the Nyquist-Shannon theorem and applies equally to both digital and analog sampling (digital sampling is merely 1-bit analog sampling).

With interrupts, since you're not sampling based on periodic checks, but instead using a hardware trigger to detect an edge (rising, falling, or changing), and assuming you have interrupts enabled at the time an edge arrives on the pin (some code disables interrupts, and interrupts can't trigger while another interrupt routine is running), you instantly know about it regardless of whatever else you are doing.

Interrupts are said to be asynchronous, whilst polling is known as synchronous.

Which method you should choose depends on many factors: the speed of your signals (pulses from sensors, buttons pressed by humans, etc), what else your program is doing, how critical it is that you detect an input state change, etc. For slow signals, like a button, polling is perfectly fine. For high speed signals, like a hall-effect sensor or a reed switch triggered by a bicycle wheel mounted magnet, interrupts are more suitable.

For some signals (especially things like revolution counters, frequency counters, etc) where you have a large number of brief pulses coming in over a period of time where all you want to do is count them, there are even better options than interrupts.

The internal timer peripherals of the chip can run in a number of modes that are designed just for this scenario. You can run a timer with the clock source as an IO pin. That means that on each incoming pulse to that IO pin the timer counts up by one. That happens completely independently of your program. You just read the current count from the timer and reset it to 0 to start counting again at a period to suit you.

Another mode is Input Compare mode. This combines normal interrupts with a timer. The timer runs in the background at a pre-defined rate, and as soon as a specific input changes state (each timer has specific inputs for this) the timer is frozen an interrupt is triggered. This gives highly accurate time measurement of incoming signals since it's not subject to the time taken to service the interrupt. The timer is frozen immediately and you can query that time when the system is able to service the interrupt.

There is no native support in Arduino for either of those timer modes, though, so you would have to either find an advanced library that configures the timers in that way for you, or read and understand the datasheet and manually configure the timers in the right way.

Majenko
  • 105,095
  • 5
  • 79
  • 137
  • so, for example, a state change, like a button toggle, is this an example of polling of the digital pin that is being read by digitalRead()? like, if a momentary button is pushed, its useless for a toggle, but if you scan the pin for a change, a HIGH or LOW, and save that change, then toggle off that change, (latch) is this is an example of polling? – Jim Jan 17 '18 at 03:32
  • Polling is merely the act of using digitalRead. – Majenko Jan 17 '18 at 09:50
  • cool, so the MCU is polling when digitalRead is used, when there is a change, save the change, and thats the state change correct? – Jim Jan 17 '18 at 13:09
  • Polling means "tell me the state of the port right now". What you do with that information is up to you. By comparing two polled states you can find a change in state. – Majenko Jan 17 '18 at 13:13
  • so whats the difference between a state change and state detection change? How does the MCU tell the difference? – Jim Jan 17 '18 at 13:15
  • "By comparing two polled states you can find a change in state" so digitalRead polls, then a change occurs, we can save with a variable, then compare with "if"? – Jim Jan 17 '18 at 13:19
  • I have no idea what a "state detection change" is. – Majenko Jan 17 '18 at 13:20
  • state change detect means like a button press or release. its in the arduino sketch libary examples – Jim Jan 17 '18 at 13:20
  • A state change detection is what your sketch does with the information returned by successive polls. – Majenko Jan 17 '18 at 13:21
  • static bool lastState = HIGH; bool state = digitalRead(3); if (state != lastState) { lastState = state; if (state == HIGH) { buttonReleased(); } else { buttonPressed(); }} – Majenko Jan 17 '18 at 13:22
  • ive seen it coded allot simplier than that dude, but thats what Im studying – Jim Jan 17 '18 at 13:24
  • That's pretty much the simplest, however that detects both state changes (HIGH->LOW and LOW->HIGH). If it's only one you need then you don't need the ELSE. – Majenko Jan 17 '18 at 13:24
  • yeah your right, sorry, thats pretty much the same code, just they had it different – Jim Jan 17 '18 at 13:25
  • a state change, then a state detection change – Jim Jan 17 '18 at 13:25
  • I still don't know what you mean by a "state detection change". That makes no sense at all. A change in the detection of a state...? How does that work? There's only state changes, and the detection of those changes of state. – Majenko Jan 17 '18 at 13:26
  • The state changes are what you are looking for, and the "detection" is the method of finding them. – Majenko Jan 17 '18 at 13:27
  • state change means a latch, not a momentary push, but the edge detection is the next change to look for, maybe used wrong word – Jim Jan 17 '18 at 13:28
  • A state change is a change in state. There are only two states that you can get from a digital pin - LOW and HIGH. Detecting those state changes doesn't give you a "latch", it only tells you when (and in what direction) the state changes. What you do with that information (use it to toggle another "latch" variable, add one to a counter, whatever) is entirely up to you. All that side of things is encapsulated in the "buttonPressed()" and "buttonReleased()" functions in my example just now. Those functions do "whatever you want to do when a button is pressed". – Majenko Jan 17 '18 at 13:30
  • like you want to toggle a button for 2 functions. just a button push does nothing but a glitch, so you got to have states. but you want to do the state change on a button push or release so use edge state detect – Jim Jan 17 '18 at 13:30
  • why are you using this function buttonReleased()? seems all you have to do is use if digitalRead(pinA) != state{ state = digitalRead(pinA); if (digitalRead(pinA)== HIGH ) { toggle another variable} – Jim Jan 17 '18 at 13:33
  • That function is a "placeholder". It means "I don't know what you want to do here, so I'll put something in to show where your code would go, and name it appropriately". It is not a function that exists. It is for you to replace with your own code to be run when the state changes in the appropriate way. – Majenko Jan 17 '18 at 13:34
  • That code you replace it with could be "rev++" for example. – Majenko Jan 17 '18 at 13:35
  • my logic is its like a ladder or steps, one condition depends on the previous one, and build from that, like the MCU is polling the pin, if there is a change, save it and build off of that. is that correct? – Jim Jan 17 '18 at 13:36
  • like if a newb like me is trying to advance from the LED on/off to a button toggle, we got to understand the logic first. and when I mean toggle I mean the LED stays on with one button push. – Jim Jan 17 '18 at 13:40
  • The LED toggle code is separate from the pin state change detection code. The LED toggle code is triggered by the pin state change detection code, though. "IF the pin has changed state AND that change is LOW->HIGH THEN toggle the LED" – Majenko Jan 17 '18 at 13:48
  • instead of AND just use another nested "if"? – Jim Jan 17 '18 at 13:59
  • Yes, it has the same effect, with the added benefit of having a simpler "else" if you need it, and splitting out the state saving from the specific HIGH->LOW case. – Majenko Jan 17 '18 at 14:00
  • Comments are not for extended discussion; this conversation has been moved to chat. – Majenko Jan 17 '18 at 15:02