Netduino home hardware projects downloads community

Jump to content


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.
Photo

Interrupts are not caught during whileloop

Interrupts

  • Please log in to reply
5 replies to this topic

#1 Ties

Ties

    New Member

  • Members
  • Pip
  • 3 posts

Posted 21 February 2013 - 08:55 AM

Hi all,
 
I'm really happy with my Netduino but now it's getting a little frustrating (well, that's developing...) I'm struggling with the following stuff;
 
In my project, I have (for this example) 2 modules (classes) Module A and Module B. Module A contains a while loop which does important stuff like reading a port. It must do this continuous till I press a button. The while loop will exit and Module B will start containing another loop doing his important stuff. It will continue doing this till I press another button which will stop Module B and starts Module A again.
 
Both buttons are interruptports so they will always react when I push them. (Well, that was the idea....)
 
The problem which I encounter is that it will react on the first time I press the button. It starts Module A and its while loop. But it stays in this loop ignoring the interrupts. Those are queued. When a breakpoint hits the while condition and I manually stop the loop, the next queued interrupt event is caught and handled.
 
My question: how can I achieve that the interrupt is fired and the while loop stops. Do I have to create another thread in which the Module A or B can run? Or am I doing something other stupid... :)
 
The above example is a reduced testversion from my project. I am creating a trigger application for my photography in which I can switch between different modes. A Lightning Trigger to catch lightning and take a picture; a Drop Trigger to control a solenoid valve for releasing waterdrops and take a picture after X ms; a Sound Trigger for popping balloons etc. These are my 'Modules' whith their loops in it. When pressing the Mode button it has to go to the next mode.
 
I hope my problem is clear and someone can kick me in a good direction!
 
Thanks in advance,
 
Ties
 
using System;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;using Toolbox.NETMF.Hardware;using Toolbox.NETMF;namespace NetduinoZandbak{    public class BaseBoard    {        #region Variables        // Buttons        private static InterruptPort btn1;        private static InterruptPort btn2;        // Switching modules.         public static ModuleA ma;        public static ModuleB mb;        // Feedback led.        private OutputPort Led;        #endregion        #region Constructor        /// <summary>        /// Main class..        /// Instance created in Program.cs        /// </summary>        public BaseBoard()        {            try            {                Led = new OutputPort(Pins.ONBOARD_LED, false);                // Button 1 init                btn1 = new InterruptPort(Pins.GPIO_PIN_D10, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);                btn1.OnInterrupt += new NativeEventHandler(btn1_OnInterrupt);                // Button 2 init                btn2 = new InterruptPort(Pins.GPIO_PIN_D11, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);                btn2.OnInterrupt += new NativeEventHandler(btn2_OnInterrupt);                Debug.Print("Ready......");                // Stanby mode and wait for interrupts...                Thread.Sleep(Timeout.Infinite);            }            catch (Exception ex)            {                Debug.Print(ex.Message);            }        }        #endregion        #region Events        /// <summary>        /// Event handler when button 1 is pressed        /// </summary>        /// <param name="data1"></param>        /// <param name="data2"></param>        /// <param name="time"></param>        void btn1_OnInterrupt(uint data1, uint data2, DateTime time)        {            try            {                if (data2 == 0)                {                    // Pressed                    Debug.Print("Button 1 pressed on " + time.TimeOfDay.ToString());                    Led.Write(!Led.Read());                    // if mb exists, stop while loop.                    if (mb != null) mb.Stop();                    if (ma == null)                        ma = new ModuleA();                    // start module A loop                    ma.Start();                }            }            catch (Exception ex)            {                Debug.Print(ex.Message);            }        }        /// <summary>        /// Event handler when button 2 is pressed        /// </summary>        /// <param name="data1"></param>        /// <param name="data2"></param>        /// <param name="time"></param>        void btn2_OnInterrupt(uint data1, uint data2, DateTime time)        {            try            {                if (data2 == 0)                {                    // Pressed                    Debug.Print("Button 2 pressed on " + time.TimeOfDay.ToString());                    Led.Write(!Led.Read());                    // if ma exists, stop while loop.                    if (ma != null) ma.Stop();                    if (mb == null)                        mb = new ModuleB();                    // start module B loop                    mb.Start();                }            }            catch (Exception ex)            {                Debug.Print(ex.Message);            }        }        #endregion    }}

EDIT: forgot code for the modules. ModuleA and ModuleB are same structure...

    public class ModuleA    {        public bool _stop = false;        public string var = "A";        public ModuleA()        {            // Constructor for module A        }        public void Start()        {            _stop = false;            while (_stop == false)            {                Thread.Sleep(200);                Debug.Print("Do important stuff. Like reading port....  Module " + var);            }        }        /// <summary>        /// Halt main routine        /// </summary>        public void Stop()        {            _stop = true;        }    }

 

 

 



#2 Stefan

Stefan

    Moderator

  • Members
  • PipPipPip
  • 1965 posts
  • LocationBreda, the Netherlands

Posted 21 February 2013 - 09:14 AM

Hi and welcome to the Netduino community!

I see one thing in your code that makes me doubt it's outcome;

private static InterruptPort btn1; private static InterruptPort btn2; private OutputPort Led;

 

The LED, which will be set in the interrupt results, is not static, where the interruptports themselves are static.

 

I don't see code from the modules, but you could try something like this:

 

 

 

public class ModuleA {	private bool LoopEnabled = true;	public void StartLoop() { 		this.LoopEnabled = true; 		while (this.LoopEnabled) {   			// The loop		}	}	public void StopLoop() {		this.LoopEnabled = false;	} }

?

?

?


"Fact that I'm a moderator doesn't make me an expert in things." Stefan, the eternal newb!
My .NETMF projects: .NETMF Toolbox / Gadgeteer Light / Some PCB designs

#3 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 21 February 2013 - 09:18 AM

Hi Ties, The way that threads work in NETMF is that each thread gets up to ~10ms to execute before the thread scheduler pulls the execution to another thread. In order to make sure that interrupts are fired in sequence, NETMF queues and timestamps them...and then fires them off in order. In multi-threaded and interrupt-driven apps, we generally avoid loops or any action that ties up the processor for long periods of time. But if you'd like to run long loops for threads, you'll probably want to create a thread and launch it there. With the newer versions of .NET MF, you can even use anonymous methods to launch code on another thread "in-line" in your code. You can also create background threads for each of your tasks and then have them wait on an AutoResetEvent waithandle. Then when your interrupt gets fired, just Set the waithandle and your background thread will come to life. This also helps keep thread count down and prevent unintentional re-entry. There are a massive number of powertools available in the C# language and NETMF, so there should be one that's great for the application at hand. We're happy to help guide the selection process. Chris

#4 Ties

Ties

    New Member

  • Members
  • Pip
  • 3 posts

Posted 21 February 2013 - 09:21 AM

Crap... forgot to add the code for the Module... Just added them in the OP....



#5 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 21 February 2013 - 10:42 AM

Hi Ties!

 

This won't help solving the problem but when you define interrupt ports for the buttons, its unecessary to catch both edges. You only need to detect either low or high edges depending on whether you want to detect buttons being pressed or released respectively. Also you only get half as many interrupts and you can skip the data2 check since it will always be the same.



#6 Ties

Ties

    New Member

  • Members
  • Pip
  • 3 posts

Posted 21 February 2013 - 10:48 AM

Thanks all for your replies. I think I'll dive into the threading for the loop thing.

 

@Hanzibal: I know it catches both edges, it's indeed not neccessary in this case, but in my main project I want to use it to set a counter value. When the up button is pressed it will continuous value++ until I release the button. (But I still have to work on that... ;) 







Also tagged with one or more of these keywords: Interrupts

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.