External Interrupt help

Hello all,
You folks helped me a short time ago with a serial communications problem I was having and I am graciously happy. However I am back begging again because I am having another problem with the project concerning interrupts. The project has 3 Nano boards to generate specific timed pulses, read analog voltages, monitor multiple switches, control colored leds, display data on an LCD display, communicate with each other via serial and generate sounds. Guess what? I managed to achieve that and it is working fine. What I am having trouble with is the coding to install an interrupt on pin d2 connected to a button switch. My goal is to use the switch to power down all 3 Nanos to a low current value instead of using an on off switch to cut the battery voltage. A second push of the switch should start things up again where it left off. I realize I might have to make sure that the outputs might have to be put into a known state before they are disconnected, but the pins are not really providing much current. Total current draw is 79 ma for all 3 devices and 171 ma if I turn the backlight on and the LED’s are only on during a short calibration period. I have read multiple ways of implementing this code and tried to put together the most common parts into something that would accomplish this, but running into problems. Either the ISR is not activated or when change code and get to do that it stays there. I once got it go there, but it was doing it itself, returning then executing again. I owe it all to my inexperience, but once I get it, I will remember it for a long time. Each Nano has it’s own code, so I suspect I will have to connect all pin d2’s together and put the code in each of them to accomplish power down. Here is a skeleton sample of where I left off in the coding. There are over 300 lines of code in the main Nano so I did not include those, just the parts with the interrupts. I hope someone can help.
Thanks in advance

Forum_sketch.ino (1.15 KB)

I think you may be encountering "bounce". We like to think that pressing a button simply activates it. In fact, it's like dropping a ball. The ball doesn't simply hit the floor and stay there. It hits the floor, springs back into the air, hits the floor... With a Switch it's the same Thing. They rarely (Special Hardware is the exception) simply go on or off once.

Also, you may be encountering Problems because your reattach Interrupts within Interrupt handling routines. That isn't even necessary. Try simply using a flag to indicate wether the sleep mode is active or not. If active, deactivate and call wake up Routine, if not active, activate and call power down routine.

Refer to:

http://forum.arduino.cc/index.php?topic=45000.0

I have never experimented with sleep() but I wonder if this should LOW, or would FALLING be better

attachInterrupt(0, PowerDown, LOW);

Using LOW will cause multiple interrupts while the pin is LOW whereas FALLING will only cause one (unless the pin goes HIGH first).

...R

Thank you JaBa and Robin2. I have implemented both of your suggestions, but I am still where i left off. I used the flag idea and the falling idea. but. It recognizes the switch input, goes to the ISR then just stays there. I used a meter to test pin 2. It goes from High to Low and back to High after a button press. A second press later does the same thing, but nothing. I attached a green led fom pin 8 to ground and turn it on when it enters the ISR. and turn it off at the end of the ISR. It turns on, but can only turn it off by pushing reset.. Can't show the updates right now, because my phone is refusing to attach the code. Will post later. Thanks for the help.

Code with interrupts is always hard to debug. You need to have a very clear concept of the steps that you want to happen and the conditions for each of them.

Probably it would be a good idea to simplify the code so it just has one ISR and get that working before trying to add another.

Have a look at Nick Gammon's interrupt tutorial

...R

Thanks again Robin2. Lots of good stuff on that link there. Near the bottom was basically what I was trying to do, but still gives the same problem. Added some LEDS to the heap to track where things were going. He made some changes The green LED lights in the Loop, then is supposed to go off in the sleep part. Then wake up if I press the button and shuts the sleep mode off and lights the red lamp and from there to the Loop. As it is setup now it goes right on through all that lights the red led for a few microseconds to the loop. I added some code to the loop to make the red and green alternate on and off when in the loop to aid in figuring out where the software was going. So the sequence should be power up, flashing red and green, press button, light the green led, go to sleep, press the button a few minutes later, wakes up lights the red light, goes back to loop. At a later time should be able to do it again, and again. Shoots right through the whole sequence and ends up at the loop when I press the button. I have other things on the Nano, so I took a separate Nano, added just a buffered switch, the dual color LED and programmed it with the sample code and had the outcome. My goal is to be able to use the sleep mode as faux power switch. (even though it does draw some current.)

Forum_sketch.ino (2.02 KB)

Hi everyone.Found a novel way to get it to work. Will post the code to a little later. Maybe it will help someone later. Most of what I posted last message is ok… Thanks for your time, patience and advice which led me to a path of success. :slight_smile:

Ok I am back. Here is what I did and the updated sketch. First I did not depend on the interrupt to activate the ISR. I instead poll pin2 at the end of the loop function. If the switch has been closed it calls MyISR like you would call a sub routine. Inside of MyISR I turn on the interrupt so when it wakes up it goes to Wake which turns the sleep mode off, and detaches the Interrupt. As it returns to the very end of the loop it loops back to the beginning where, after a short delay, the interrupt is again turned on and set to MyISR. There are some delays mixed in at certain places to act as debouncers . But it works most of the time. Some tiny glitches to iron out. My next chore, which I have already started on, is to connect all 3 Nanos to the reset button. Initial current measurements are for everything running 71 Ma. In sleep mode it draws 26 Ma. This is using 4.5 volts on the 5 volt line and no leds on and the LCD backlight off. Almost a complete project, except for making circuit boards, etc. Suspect I will have to use an external debouncer to get all 3 boards to synchronize in the power up and down. All boards have the same power up/down scheme.

Forum_sketch2.ino (2.68 KB)

When you write such long paragraphs it makes your stuff almost impossible to read - so much so that I am not prepared to try.

A good test as to whether a piece of text is understandable is to read it to yourself out loud,

…R

Sorry for the long paragraphs. The problem came back again. Switched to a bounceless switch. It has a single 100 millisec positive going negative pulse output. No help
I rewrote the code and made some changes. no help. Here is what I have now. The Green lite comes on for a few seconds then the code slides right through my test for input on pin 2 without me touching anything. Then the Red light comes on. I Press the switch, red light goes out, green light comes on then goes through this sequence again and again. I Haven’t figured out why the switch test lets the code get by.
I have 2 other NANOs using this same code and they work. Maybe something wrong with the board?

external_input_problrm.ino (1.09 KB)

The text in Reply #10 is a little easier to read - but putting a blank line between paragraphs would further improve the readability enormously.

In the code you have posted in Reply #10 it is the function "Wake" that is the Interrupt Service Routing (ISR). The function you have called "MyISR" is just an ordinary function and should have an ordinary name such as setForSleep().

You have told us what the code does, but it would be a big help if you tell us what it is supposed to do. A step by step description of what should happen with each step on a separate line would be a big help

I suspect all those long delay()s don't help.

...R

Thank you for your replay Robin2. The posted code is a piece of a much larger program. I broke it out to test its functioning. It doesn’t work properly in either case.

It’s function was supposed to be used as a way to power down 3 Nanos in a project that generates multiple pulses to control a machine. The other 2 Nanos work with this code installed.

The posted code is supposed to first turn on the green light (used to indicate it is in the loop and not in the ISR.) and stay in the loop. When the button on pin 2 is pressed, it should then goto the section I labeled MyISR and, turn off the green light and turn on the red light (to indicate it is no longer in the loop). Then it should put the Nano into the sleep mode.

When the button is pressed again it should leave MyISR and go to Wait. There it should turn off the red light and disable sleep and go back to the loop mode.

It just turns the green light on, delays for a short bit then turns the red light on and stays there until the button is pressed. Then it turns the red light off, delays a bit, turns the green light on, delays then turns the green light off and the red light on and waits.

This is how I would write the behaviour and the requirement to make it all crystal clear (I am just using your text)

What it does

  • It just turns the green light on,
  • delays for a short bit then
  • turns the red light on and
  • stays there until the button is pressed. Then it
  • turns the red light off,
  • delays a bit,
  • turns the green light on,
  • delays then
  • turns the green light off and
  • the red light on and

- waits.

What is wanted

  • first turn on the green light (used to indicate it is in the loop and not in the ISR.) and
  • stay in the loop.
  • When the button on pin 2 is pressed, it should then
  • goto the section I labeled MyISR and,
  • turn off the green light and
  • turn on the red light (to indicate it is no longer in the loop). Then it should
  • put the Nano into the sleep mode.
  • When the button is pressed again it should leave MyISR and go to Wait. There it should
  • turn off the red light and
  • disable sleep and
  • go back to the loop mode.

I am not familiar with sleep() but my feeling is that your code is too convoluted. You have an attachInterrupt() for the button switch and you have a digitialRead() bot going to the same function. But the way the function is used will be different.

It is probably not helpful to describe the code like "goto the section ...". The correct terminology is "call the function ..." and to my mind that conveys a different concept because functions return to the code that called them.

If it was my project I would only have the Wake() ISR that operates to wake the thing up. There is no need to use interrupts for buttons that are pressed by humans.

...R