The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
I was trying to solve the classic problems around a bouncing contact for my Beer Timer project, and i got caught up into trying to understand all about how an simple InterruptPort works.
Now from what i seem to read InterruptEdgeHigh and InterruptEdgeLevelHigh is generating an interrupt at the same time, on the rising edge, but the latter one is only generating one interrupt and then disables interrupts until the .ClearInterrupt() method is called on the InteruptPort object.
However running the code below, is working fine, but trying to use the "level" type InterruptModes fails with an error, when i try to subscribe to the interrupt event.
A first chance exception of type 'System.ArgumentException' occurred in Microsoft.SPOT.Hardware.dll
on:
Button.OnInterrupt += new NativeEventHandler(Button_OnInterrupt);
The full code is here, however the failing lines is commented out:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
namespace NP2.Example_Button_InterruptPort
{
public class Program
{
static OutputPort Led;
static InterruptPort Button;
static DateTime Button_LastInterruptTime = DateTime.Now;
static Boolean Led_State = false;
public static void Main()
{
Led = new OutputPort(Pins.ONBOARD_LED, false);
Button = new InterruptPort(Pins.ONBOARD_BTN, false, ResistorModes.Disabled, InterruptModes.InterruptEdgeHigh);
//Button = new InterruptPort(Pins.ONBOARD_BTN, false, ResistorModes.Disabled, InterruptModes.InterruptEdgeLevelHigh);
Button.OnInterrupt += new NativeEventHandler(Button_OnInterrupt);
Thread.Sleep(Timeout.Infinite);
}
static void Button_OnInterrupt(uint port, uint state, DateTime time)
{
if (Button_LastInterruptTime.AddMilliseconds(200) < time)
{
Led_State = !Led_State;
Button_LastInterruptTime = time;
Led.Write(Led_State);
}
//Thread.Sleep(10);
//Button.ClearInterrupt();
}
}
}
Why is it not working, is there another thing i do not know yet. :-)
Hi Ulrik,
You are correct...the level interrupts fire once and then auto-disable. It's a useful feature for single-shot interrupts.
Each family of microcontroller has its own HAL for NETMF. Some implement the level interrupts and some do not. The core STM32 HAL does not.
That said...let's add this to the STM32 core. I've added to our short list of new features to add to Netduino Plus 2. We should be able to carry it across to Netduino Go as well.
Is this a blocking issue for you? We're trying to keep the frequency of updates to a reasonable number...but we could get you a beta release with this feature within a few days if you're in need
Chris
That said...let's add this to the STM32 core. I've added to our short list of new features to add to Netduino Plus 2. We should be able to carry it across to Netduino Go as well.
Nice, very nice indeed.
Is this a blocking issue for you? We're trying to keep the frequency of updates to a reasonable number...but we could get you a beta release with this feature within a few days if you're in need
It's not a blocking issue at all, and the code above is an example on how you can live without this feature perfectly fine in the case of manual contacts or relays.
But in the future i think level interupts will be nice to have, as the solution is cleaner and more understandable.
People that are new into electronics often forget that contacts bounces, and the MCU they are using is fast enough to detect that, several times for every press/change.
And the netduinos do attract a lot of those people, myself included.
... People that are new into electronics often forget that contacts bounces, and the MCU they are using is fast enough to detect that, several times for every press/change. ...
That being said, I am curious: do you find that the glitch filter option of the input port to be ineffective? debounce is truly one of my very least favorite chores, so I was pleased to see this in .NETMF
That being said, I am curious: do you find that the glitch filter option of the input port to be ineffective? debounce is truly one of my very least favorite chores, so I was pleased to see this in .NETMF
The glitch filter does not help much to handle debouncing, because it samples the input during very short time period, usually only a few microseconds (e.g. four times 'get pin state' native function call, which is basically direct GPIO register access with some overhead), bouncing occurs in time intervals orders of magnitude longer, tens or even hundreds of milliseconds, depending on the switch mechanical construction.
The glitch filter does not help much to handle debouncing, because it samples the input during very short time period, usually only a few microseconds...
Oh, interesting, I thought keybounce was the whole raison detre for glitch filter. Actually googling "netmf glitch filter" yields some indications that this is the intended purpose (e.g. first hit http://wiki.microfra.../index.php/GPIO and also the Microsoft http://msdn.microsof...y/cc532245.aspx); not that I believe everything I read on the web! But yes microseconds is too short, I usually use 20-50ms in my c/asm code implementations...
Oh, interesting, I thought keybounce was the whole raison detre for glitch filter. Actually googling "netmf glitch filter" yields some indications that this is the intended purpose (e.g. first hit http://wiki.microfra.../index.php/GPIO and also the Microsoft http://msdn.microsof...y/cc532245.aspx); not that I believe everything I read on the web! But yes microseconds is too short, I usually use 20-50ms in my c/asm code implementations...
You can actually Get and Set the Cpu.GlitchFilterTime yourself, but as it works globally i have opted out of that solution, simply because i am afraid it might affect "other stuff" too.
With the fast CPU's we have the glitch filter might be able to filter out some noice, or not clean signals from other circuits, but for bounces from manual keys it's not usable.
I originally tested the glitch filter on the onboard button, and there was no noticeable difference whether used or not.
I was trying to solve the classic problems around a bouncing contact for my Beer Timer project, and i got caught up into trying to understand all about how an simple InterruptPort works.
Now from what i seem to read InterruptEdgeHigh and InterruptEdgeLevelHigh is generating an interrupt at the same time, on the rising edge, but the latter one is only generating one interrupt and then disables interrupts until the .ClearInterrupt() method is called on the InteruptPort object.
However running the code below, is working fine, but trying to use the "level" type InterruptModes fails with an error, when i try to subscribe to the interrupt event.
[font="'Courier New';"]A first chance exception of type 'System.ArgumentException' occurred in Microsoft.SPOT.Hardware.dll[/font]
on:
Button.OnInterrupt += new NativeEventHandler(Button_OnInterrupt);
The full code is here, however the failing lines is commented out:
using System;using System.Net;using System.Net.Sockets;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;namespace NP2.Example_Button_InterruptPort{ public class Program { static OutputPort Led; static InterruptPort Button; static DateTime Button_LastInterruptTime = DateTime.Now; static Boolean Led_State = false; public static void Main() { Led = new OutputPort(Pins.ONBOARD_LED, false); Button = new InterruptPort(Pins.ONBOARD_BTN, false, ResistorModes.Disabled, InterruptModes.InterruptEdgeHigh); //Button = new InterruptPort(Pins.ONBOARD_BTN, false, ResistorModes.Disabled, InterruptModes.InterruptEdgeLevelHigh); Button.OnInterrupt += new NativeEventHandler(Button_OnInterrupt); Thread.Sleep(Timeout.Infinite); } static void Button_OnInterrupt(uint port, uint state, DateTime time) { if (Button_LastInterruptTime.AddMilliseconds(200) < time) { Led_State = !Led_State; Button_LastInterruptTime = time; Led.Write(Led_State); } //Thread.Sleep(10); //Button.ClearInterrupt(); } }}
Why is it not working, is there another thing i do not know yet. :-)
- Ulrik
Hi There!
I was trying to solve the classic problems around a bouncing contact for my Beer Timer project, and i got caught up into trying to understand all about how an simple InterruptPort works.
Now from what i seem to read InterruptEdgeHigh and InterruptEdgeLevelHigh is generating an interrupt at the same time, on the rising edge, but the latter one is only generating one interrupt and then disables interrupts until the .ClearInterrupt() method is called on the InteruptPort object.
However running the code below, is working fine, but trying to use the "level" type InterruptModes fails with an error, when i try to subscribe to the interrupt event.
[font="'Courier New';"]A first chance exception of type 'System.ArgumentException' occurred in Microsoft.SPOT.Hardware.dll[/font]
on:
Button.OnInterrupt += new NativeEventHandler(Button_OnInterrupt);
The full code is here, however the failing lines is commented out:
using System;using System.Net;using System.Net.Sockets;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;namespace NP2.Example_Button_InterruptPort{ public class Program { static OutputPort Led; static InterruptPort Button; static DateTime Button_LastInterruptTime = DateTime.Now; static Boolean Led_State = false; public static void Main() { Led = new OutputPort(Pins.ONBOARD_LED, false); Button = new InterruptPort(Pins.ONBOARD_BTN, false, ResistorModes.Disabled, InterruptModes.InterruptEdgeHigh); //Button = new InterruptPort(Pins.ONBOARD_BTN, false, ResistorModes.Disabled, InterruptModes.InterruptEdgeLevelHigh); Button.OnInterrupt += new NativeEventHandler(Button_OnInterrupt); Thread.Sleep(Timeout.Infinite); } static void Button_OnInterrupt(uint port, uint state, DateTime time) { if (Button_LastInterruptTime.AddMilliseconds(200) < time) { Led_State = !Led_State; Button_LastInterruptTime = time; Led.Write(Led_State); } //Thread.Sleep(10); //Button.ClearInterrupt(); } }}
Why is it not working, is there another thing i do not know yet. :-)
- Ulrik
Ulrik, thanks for your exaple sketch. How would onInterrupt work if we had multiple inputs to watch and if any is ON do something?
Ulrik, thanks for your example sketch. How would you program "onInterrupt" if we
had multiple inputs to watch and if any is ON do something?
If i understand you correctly you have a case where you would want to react on more than one button, in that case i would create more interuptports, subscripe to interupts from all ports from one generic eventhandler.
That eventhandler would now get all interrupts, but they are fired with parameters, you should look for the port parameter, that should show you from what interuptport the interupt is coming.