Netduino home hardware projects downloads community

Jump to content


Photo

How to pause a program execution without a timer?

Pause a program execution

  • Please log in to reply
5 replies to this topic

#1 shimoda

shimoda

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationQuebec, Canada

Posted 26 August 2015 - 09:15 PM

How can I pause a program execution temporary to handle an unforeseen event? 

 

I have a system monitoring many temperature sensors in order to heat or chill a chamber. I want the user to be able to pause the program in order to handle something unexpected by pressing an emergency switch. After the problem is resolved the user will reset the emergency switch giving the signal to the program to resume its monitoring, heating and cooling activities. 

 

I am quite new to Netduino and C# environment. I have a netduino 1 on MF4.2. 

 

Thanks for your suggestion! 



#2 shimoda

shimoda

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationQuebec, Canada

Posted 27 August 2015 - 01:51 AM

        public static void Run() {
            while (true)
            {
                if (errorSignal.Read() == false) 
                //Read the signal on the GPIO port. This signal is maintain until the switch is reset.
                {
                    //The emergency stop switch is active. Pause the program execution.
                    emergencyStopEvent(new object(), EventArgs.Empty); //Stop all heating components, timers...
                    while (true)
                    {
                        if (errorSignal.Read() == true) 
                        //Read the signal on the GPIO port. The switch has been reset.
                        {
                            //There is a request to resume the program execution.
                            break;
                        }
                    }
                }
                ReadSensorValuesAndDoStuff();
            }
        }


#3 shimoda

shimoda

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationQuebec, Canada

Posted 27 August 2015 - 01:54 AM

        public static void Run() {
            while (true)
            {
                if (errorSignal.Read() == false) 
                //Read the signal on the GPIO port. This signal is maintain until the switch is reset.
                {
                    //The emergency stop switch is active. Pause the program execution.
                    emergencyStopEvent(new object(), EventArgs.Empty); //Stop all heating components, timers...
                    while (true)
                    {
                        if (errorSignal.Read() == true) 
                        //Read the signal on the GPIO port. The switch has been reset.
                        {
                            //There is a request to resume the program execution.
                            break;
                        }
                    }
                }
                ReadSensorValuesAndDoStuff();
            }
        }

What would be a better approach to wait for the activation/desactivation of the GPIO port (user emergency switch) in order to pause and resume the program execution?  



#4 dranuag

dranuag

    New Member

  • Members
  • Pip
  • 9 posts
  • LocationLuxembourg

Posted 28 August 2015 - 10:58 AM

Hi, 

 

I am not sure I fully understood what how the GPIO port behaves in your example, but assuming it can generate interrupts as the board's button does, I would use a Timer instead of a while loop and write something like the following example. 

 

N.B. I did not get the occasion to compile/test the following code, adapted from something I did here. It's thus just the general idea of what I would do. 

 

using System.Timers;
 
public class Process
{
    const int STARTUP_TIME = 5000;
    const int PERIOD = 1000; //We assume that ReadSensorValuesAndDoStuff() execution takes less than 1 second
 
    bool isEnabled = true; 
 
    InterruptPort button = new InterruptPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
 
    public Process() 
    {
          button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);
 
          TimerCallback workTimerCallBack = DoWork;
          Timer workTimer = new Timer(workTimerCallBack, null, STARTUP_TIME, PERIOD);
     }
 
     private void DoWork(object state)
     {
          if (isEnabled)
          {
               ReadSensorValuesAndDoStuff();
          }
     }
 
    void button_OnInterrupt(uint data1, uint data2, DateTime time)
     {
          isEnabled = !isEnabled; 
     }
}
 
Every second, DoWork() will be called and, if isActive is true (which is the default value), ReadSensorValuesAndDoStuff() will be called.
 
When the board's button is pushed, the _OnInterrupt handler will be called and the isActive will be inverted, going from true to false, stopping the calls to ReadSensor...(). When the button will be released or pushed again (depending on the chosen Port.InterruptMode), the isActive variable will be returned to true, and ReadSensorValuesAndDoStuff() will be called again. 
 
Note that with .NET, a Timer has an "enabled" property that I would use instead of the isEnabled variable.
 
Hope it helps, 
 
Paul 
 
P.S. While verifying my posted answer, I noticed the "without a Timer" in the title of your post  :unsure:  


#5 shimoda

shimoda

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationQuebec, Canada

Posted 09 September 2015 - 07:51 PM

 

Hi, 

 

I am not sure I fully understood what how the GPIO port behaves in your example, but assuming it can generate interrupts as the board's button does, I would use a Timer instead of a while loop and write something like the following example. 

 

N.B. I did not get the occasion to compile/test the following code, adapted from something I did here. It's thus just the general idea of what I would do. 

 

using System.Timers;
 
public class Process
{
    const int STARTUP_TIME = 5000;
    const int PERIOD = 1000; //We assume that ReadSensorValuesAndDoStuff() execution takes less than 1 second
 
    bool isEnabled = true; 
 
    InterruptPort button = new InterruptPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
 
    public Process() 
    {
          button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);
 
          TimerCallback workTimerCallBack = DoWork;
          Timer workTimer = new Timer(workTimerCallBack, null, STARTUP_TIME, PERIOD);
     }
 
     private void DoWork(object state)
     {
          if (isEnabled)
          {
               ReadSensorValuesAndDoStuff();
          }
     }
 
    void button_OnInterrupt(uint data1, uint data2, DateTime time)
     {
          isEnabled = !isEnabled; 
     }
}
 
Every second, DoWork() will be called and, if isActive is true (which is the default value), ReadSensorValuesAndDoStuff() will be called.
 
When the board's button is pushed, the _OnInterrupt handler will be called and the isActive will be inverted, going from true to false, stopping the calls to ReadSensor...(). When the button will be released or pushed again (depending on the chosen Port.InterruptMode), the isActive variable will be returned to true, and ReadSensorValuesAndDoStuff() will be called again. 
 
Note that with .NET, a Timer has an "enabled" property that I would use instead of the isEnabled variable.
 
Hope it helps, 
 
Paul 
 
P.S. While verifying my posted answer, I noticed the "without a Timer" in the title of your post  :unsure:  

 

Thanks Paul for you idea. It opens my mind to concept I did not know. Therefore, in my context my system will be doing stuff none stop, so timer is not the best option unless I put the period to 0 second.



#6 shimoda

shimoda

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationQuebec, Canada

Posted 09 September 2015 - 07:57 PM

Here is the solution I have developed based on my search.

 

I will be happy to learn from your comments.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace ReadInterruptGPIOfromThread
{
    public class Program
    {
        InterruptPort button = new InterruptPort(Pins.ONBOARD_BTN, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelHigh);

        Thread runT = new Thread(new ThreadStart(p.Run));     //Thread to execute the main program.
        protected Boolean runTRunning = false;

        public static Program p = new Program();
        public static void Main()
        {
            p.Subscribe();
            Thread.Sleep(Timeout.Infinite); //Waiting for an event.
        }

        public void Subscribe()
        {
            button.OnInterrupt += new NativeEventHandler(doOnButton);
        }

        public void Run()
        {
            while (true)
            {
                Print();  
                Thread.Sleep(1000);
            }
        }

        public void Print() //The content of this function will be replaced by the real purpose of the program.
        {
            Debug.Print("Running");
        }

        public void doOnButton(uint data1, uint data2, DateTime time)
        {
            Debug.Print("Button triggered!: " + data2);
            button.ClearInterrupt();
            if (!runT.IsAlive)
            { //On the first button pressed, the program starts. Next times it toggles between Suspend and Resume (else condition).
                Debug.Print("Started!" + data2);
                runTRunning = true; 
                runT.Start();
            }
            else
            {
                if (runTRunning == false)
                {
                    Debug.Print("Resumed!" + data2);
                    runT.Resume();
                    runTRunning = true;
                }
                else
                {
                    Debug.Print("Suspended!" + data2);
                    runT.Suspend();
                    runTRunning = false;
                }
            }
        }
    }
}






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.