Best Answer ShVerni, 17 May 2014 - 01:14 AM
Hello,
If you'd like to do everything in one loop, this seems like the easiest solution:
public class Program { private static bool _blink = true; private static OutputPort _led = new OutputPort(Pins.ONBOARD_LED, false); private static InputPort _button = new InputPort(Pins.ONBOARD_BTN, false, Port.ResistorMode.Disabled); public static void Main() { while(true) { if (_button.Read()) _blink = !_blink; if (_blink) _led.Write(!_led.Read()); //Sets the LED to the opposite of its current state Thread.Sleep(250); } } }
Now obviously there are some downsides to this approach, mainly that the button is only polled every 250 ms, so the button may not be very responsive and could be "missed" as you noticed.
Now, the idea you had of using two loops in different threads could look something like this:
public class Program { private static bool _blink = true; private static OutputPort _led = new OutputPort(Pins.ONBOARD_LED, false); private static InputPort _button = new InputPort(Pins.ONBOARD_BTN, false, Port.ResistorMode.Disabled); public static void Main() { //Start button polling thread new Thread(buttonLoop).Start(); while(true) { if (_blink) _led.Write(!_led.Read()); Thread.Sleep(250); } } private static void buttonLoop() { while (true) { if (_button.Read()) _blink = !_blink; Thread.Sleep(50); } } }
You could try tuning the Thread.Sleep call in the buttonLoop to get the responsiveness you'd like, but there's still a lot of wasted overhead looping through things and polling the button. Plus, there's still a chance of "missing" the button press or reading too many presses.
This brings us to the event driven method, which is probably the most elegant solution, and uses an interrupt port for the button:
public class Program { private static bool _blink = true; private static OutputPort _led = new OutputPort(Pins.ONBOARD_LED, false); private static InterruptPort _button = new InterruptPort(Pins.ONBOARD_BTN, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh); public static void Main() { //Attach the interrupt event _button.OnInterrupt += _button_OnInterrupt; while(true) { if (_blink) _led.Write(!_led.Read()); Thread.Sleep(250); } } static void _button_OnInterrupt(uint port, uint status, DateTime time) { Debug.Print("Button pushed"); _blink = !_blink; } }
I should make a note to notice this parameter in the InterruptPort: Port.InterruptMode.InterruptEdgeHigh. That sets the interrupt to trigger whenever it sees a "high" logic value, essentially when the button would be read as True. I actually forget if the onboard_btn when pressed gives a "high" or "low" logic signal. If that doesn't work, try changing that parameter to Port.InterruptMode.InterruptEdgeLow. This also applies to all the times I called _button.Read() in my other examples, if things aren't working right you might need to change them to !_button.Read().
Also, if you use the interrupt method, you'll probably notice a lot of "bounce", which is the button quickly triggering multiple times as you press it, so you'll have to lean a bit about debouncing, and this post is a good place to start:
http://forums.netdui...upt/#entry55487
That thread also has some good infomation on buttons and interrupts in general. There are definitely other ways to do this sort of thing, but this should be a good start.
Good luck!
Go to the full post