Netduino InterruptPort Inconsistency - c#

Im writing a Netduino 3 program that will control turn lights and other relays for hayrides. My program was written before I got the device, so Im not sure how well it will work, but Im already having a problem with one of the buttons (hazardButton). When applying 3.3v it doesn't cause the interrupt to trigger. Applying 5v does the same, however when applying GND it triggers the interrupt, but when re-applying GND it doesn't turn off the interrupt.
Here's my code:
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 Tractor_Mate
{
public class Program
{
static InterruptPort hazardButton = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
static OutputPort hazardLights = new OutputPort(Pins.ONBOARD_LED, false);
static bool hazardsActive = false;
public static void Main()
{
Debug.Print("Initializing Inputs... ");
hazardButton.OnInterrupt += new NativeEventHandler(hazardButton_OnInterrupt);
Thread.Sleep(Timeout.Infinite);
}
static void hazardButton_OnInterrupt(uint data1, uint data2, DateTime time)
{
while (data2 == 0)
{
hazardLights.Write(true);
Thread.Sleep(500);
hazardLights.Write(false);
Thread.Sleep(500);
hazardsActive = true;
}
hazardsActive = false;
}
}
}
Im getting the problem with the Hazard Lights and haven't tried any of the others yet. Im wiring the buttons up so that when the pin goes HIGH it will trigger, and then when LOW it turns it off.

public class Program
{
static InterruptPort hazardButton = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
static OutputPort hazardLights = new OutputPort(Pins.ONBOARD_LED, false);
static volatile bool hazardsActive = false;
public static void Main()
{
Debug.Print("Initializing Inputs... ");
hazardButton.OnInterrupt += new NativeEventHandler(hazardButton_OnInterrupt);
bool lightOn = true;
while (true)
{
if (!hazardsActive)
{
hazardLights.Write(false);
}
else
{
hazardLights.Write(lightOn);
lightOn = !lightOn;
}
Thread.Sleep(500);
}
}
static void hazardButton_OnInterrupt(uint data1, uint data2, DateTime time)
{
hazardsActive = !hazardsActive;
}
}
I'm unable to test this since I don't have the Netduino SDK installed (I have a NetDuino, but its been a while since I played with it). The principle is pretty easy:
The interrupt only toggles the hazards being on or off. The variable is marked volatile because it can be set from multiple threads and it needs to be read from the register not a thread cache, so volatile tells the compiler not to optimize it.
The main method has an infinite loop that examines if the hazards are on or off. When the hazards are off (first part of the if), it writes false to the output pin (presumably turning the lights off, unless the pin is inverted).
When the hazards are on (else part), it writes a value to the pin then inverts the value so the next time it turns it off, then on, then off, etc. The last part of the loop just waits 500ms before looping again.
Note
Depending on the "quality" of the contacts in the button you are using, you may need to add debouncing logic to the interrupt handler. "Bouncing" is a phenomenon with switch contacts (or any other mechanical contact) that can cause the contact to open/close many times very quickly when changing state. This is due to the electrical signal bridging the gap as the contacts are very close to each other (think static electricity jumping a gap). A lot of times this is handled on the hardware side by a capacitor, but I'm not sure for the Netduino how it handles it.

Related

Restarting a method

I am making a C# aplication. I have got one main process for verifying data from a database. A timer checks every 100 ticks if I have user input. After I get user input my main process continues (it waits for userinput at the start). After verifying and doing multiple things the method is done. The thing is, I would like it to go to the beginning again waiting for the next bit of input.
I was thinking of calling the method again at every possible end of the process. I have a feeling that this will create a resource heavy program though (not the worst thing, but better no bad habits than a few right?).
Example:
bool cont = false;
public void process()
{
while (cont == false) {;}
//Various sorting criteria that all end up with cont = false; process(), the userinput has been processed.
}
timer1 tick event
{
if (userinput)
cont = true;
}
As you don't saw how you will get the user input, i don't implemented this one. But the main logic to your question is :
class MainClass
{
public static void Main()
{
MyRecursiveFunction();
AfterUserInput();
}
public static void MyRecursiveFunction()
{
if (userinput)
{ return; }
// Waits 100 ticks to check again
Thread.Sleep(new TimeSpan(100));
MyRecursiveFunction();
}
public static void AfterUserInput()
{
// All that you need to do after the user input
}
}

How to stop the Console from pausing my Threads and Tasks?

When I am using the scrollbar in the console window all Threads and Tasks are getting paused. Are there any ways to prevent that from happening?
example:
Task.Run(async () =>
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
await Task.Delay(200);
}
});
or
var s = new Thread(() =>
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
Thread.Sleep(200);
}
});
If you run either one of these code samples as a console application, both will do the same: print some numbers. During execution hold the scrollbar with your left mouse button for some time and the numbers will stop coming up. The Task/Thread has been paused. When you release the mouse button the numbers will continue.
Because the number after the release of the scroll bar follows the one before, the console has not simply stopped the output of the numbers. It has been waiting in the Console.WriteLine - method until a am releasing the scroll bar.
Does anyone know how to fix my problem?
There is not much you can do to stop this. Console.WriteLine will block while you are holding down your scroll bar, this has nothing to do with threads or tasks at all. The following small program shows the same issue.
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
Thread.Sleep(200);
}
}
}
}
You can't change the behavior of Console.WriteLine the only thing you can do is put a buffer between you and the writes to the console.
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//The writer lives in another thread.
var s = new Thread(ConsoleWriter);
s.Start();
for (var z = 0; true; z++)
{
//This add call does not get blocked when Console.WriteLine gets blocked.
LinesToWrite.Add(z.ToString());
Thread.Sleep(200);
}
}
static void ConsoleWriter()
{
foreach (var line in LinesToWrite.GetConsumingEnumerable())
{
//This will get blocked while you hold down the scroll bar but
// when you let go it will quickly catch up.
Console.WriteLine(line);
}
}
static readonly BlockingCollection<string> LinesToWrite = new BlockingCollection<string>();
}
}
This is only a quick and dirty solution to this, there are other ways of solving this to make it more transparent like making a class derived from TextWriter that will buffer the calls and using that class in a call to Console.SetOut(.
You'll need to asynchronously write to the console if you don't want the code to block when access to the console is locked (in this case, by the user), and not wait for that asynchronous operation to finish before continuing on. This can be done as simply as using Task.Run(() => Console.WriteLine(z)) in place of Console.WriteLine(z).
You'll also need to make a copy (before the call to Run) of any closed over variables that will end up being mutated after the call to Task.Run, since closures close over variables rather than values.
That said, it's a strong indication that you should re-consider your design here. Perhaps the console isn't the right way for you to output your data; another type of UI may be appropriate.

How to put a Fez Panda II to 'Sleep' mode via button control?

I have a Fez Panda 2 with a simple switch wired into pin Di20. I have it declared as
static InputPort MySwitch = new InputPort((Cpu_Pin)FEZ_Pin.Digital.Di20, false, Port.ResistorMode.PullUp);
I have several threads in my program, one of which runs a while(true) block in which I want to use:
while(true)
{
if(MySwitch.Read()== false)
{
//put FEZ to sleep
LED.State = LED.LedState.Off; //I have an LED class to set LED on or off
}
else
{
//wake up FEZ
LED.State = LED.LedState.Off;
}
}
Any idea on how I could achieve this so that the Fez will 'hibernate' until this button is changed?
I have heard about allowing An interrupt Port, but I am unsure if this is useful/feasible in this situation. I have several COM ports connected, and want these connections to 'close' and so 'stop' all transmissions. It is due to these serial ports that it proves difficult to 'just use an interrupt port', as well I need to 'disable' the communications there (Serials are using COM1, COM3 and COM4, with regular data flowing).
Any suggestions as to how to go about this?
Low-Power-State example below taken from here:
https://www.ghielectronics.com/docs/141/low-power
using Microsoft.SPOT.Hardware;
using System;
public class Program
{
public static void Main()
{
var interrupt = new InterruptPort(Cpu.Pin.GPIO_Pin0, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeHigh);
interrupt.OnInterrupt += interrupt_OnInterrupt;
PowerState.Sleep(SleepLevel.DeepSleep, HardwareEvent.OEMReserved1);
///Continue on with your program here
}
private static void interrupt_OnInterrupt(uint data1, uint data2, DateTime time)
{
//Interrupted
}
}

pausing program without interrupting timers c#

I am writing a program that has several "Worker" objects going off and doing tasks that take as set amount of time. I have created a worker class with an internal timer that is working fine. However, when doing the "work" i will at times need to wait several seconds for a screen refresh (each worker is scraping data from a remote screen and doing some automation).
For those pauses, i don't want to sleep the thread, because as i understand it that will also
pause the timers on the other worker objects (my application is a single thread because, frankly, I'm brand new to C# and i didn't want to overreach). Is there another waiting function that i can use that doesn't actually hang the whole thread?
Some additional info:
Right now this is a console app, but i will eventually be building a UI form to provide feedback to the user on how the workers are doing
My timers are implemented using System.Timers and are working quite nicely
I am brand new to C# programming, this is my first project, so please use small words ;)
Using MS VS Express 2012 for Desktop (so whatever version of C# / .NET that is!)
Code below (the actual work will be done using the "startWorking" method, but nothing is implemented - this is just my sold build with timers working. Also, the main is just being used for testing multiple timers right now)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace Multi_Timers
{
//worker class that includes a timer
public class Worker
{
private Timer taskTimer;
private bool available = true;
private string workerName;
private string startWork;
private int workTime;
// properties
public bool isAvailable { get { return this.available; } }
public string name { get { return this.workerName; } }
// constructor
public Worker(string name)
{
this.workerName = name;
Console.WriteLine("{0} is initialized", name);
}
// start work timer
public void startWorking(int duration) {
if (this.available == true)
{
this.available = false;
this.taskTimer = new Timer();
this.taskTimer.Interval = duration;
this.taskTimer.Elapsed += new ElapsedEventHandler(doneWorking);
this.taskTimer.Enabled = true;
this.startWork = DateTime.Now.ToString();
this.workTime = duration / 1000;
}
else Console.WriteLine("Sorry, {0} was not available to work", this.workerName);
}
// Handler for timer
public void doneWorking(object sender, ElapsedEventArgs e)
{
Console.WriteLine("{0}: {1} / {2} min / {3}", this.workerName, this.startWork, this.workTime/60, e.SignalTime.ToLocalTime());
this.taskTimer.Enabled = false;
this.available = true;
}
}
//main program
class Program
{
static void Main(string[] args)
{
Random r = new Random();
// initialize worker(s)
Worker bob = new Worker("Bob");
Worker bill = new Worker("Bill");
Worker jim = new Worker("Jim");
// q to exit
while (true)
{
if (bob.isAvailable) {
bob.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
}
if (bill.isAvailable)
{
bill.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
}
if (jim.isAvailable)
{
jim.startWorking(r.Next(1 * 60, 150 * 60) * 1000);
}
}
}
}
}
Thank you for any help in advance! Reading examples from this community was definitely key in teaching myself a little bit of C# to get started with!
i don't want to sleep the thread, because as i understand it that will also pause the timers on the other worker objects
That is incorrect; it will not stop the timers.
my application is a single thread
No, actually, it's not. The timers will be creating and using other threads to implement their behavior. The Elapsed event handlers will be fired from a thread pool thread.
One major issue with your code is that your main method is doing a "busywait" on the three objects, constantly polling them asking if they're done. This is...expensive. It's basically like you're kids asking, "Are we there yet." a few hundred times a second. Wouldn't it be so much nicer if they just sat their waiting until you told them you were done! (That's quite possible, and a good possible option.)
One of the simpler solutions in this case would be to do the loop in the worker, not Main. Have the implementation of startWorking wrapped in a while loop, and have main just do a wait forever (i.e. Thread.Sleep(Timeout.Infinite);). More complex options would be having the workers provide a Task, event, or blocking wait (also called a "Join") method to indicate when they are finished.
The option you're considering, that of adding a Thread.Sleep of a little while in Main will help, but it's only telling your kids to ask you when you're there less often, rather than having them wait for you to tell them when you're there.
If you ever find yourself wanting to delay execution again in a different context you could consider an implementation like this:
private static void DelayExecution(Action action, TimeSpan delay)
{
TimeSpan start = DateTime.Now.TimeOfDay;
Thread t = new Thread(() =>
{
while (DateTime.Now.TimeOfDay < start.Add(delay))
{
//Block
}
action.Invoke();
});
t.Start();
}
private static void Main(string[] args)
{
DelayExecution(() => Console.WriteLine("Delayed Execution"), TimeSpan.FromSeconds(1));
Console.ReadLine();
}

How to delay program for a certain number of milliseconds, or until a key is pressed?

I need to delay my program's execution for a specified number of milliseconds, but also want the user to be able to escape the wait when a key is pressed. If no key is pressed the program should wait for the specified number of milliseconds.
I have been using Thread.Sleep to halt the program (which in the context of my program I think is ok as the UI is set to minimise during the execution of the main method).
I have thought about doing something like this:
while(GetAsyncKeyState(System.Windows.Forms.Keys.Escape) == 0 || waitTime > totalWait)
{
Thread.Sleep(100);
waitTime += 100;
}
As Thread.Sleep will wait until at least the time specified before waking the thread up, there will obviously be a large unwanted extra delay as it is scaled up in the while loop.
Is there some sort of method that will sleep for a specified amount of time but only while a condition holds true? Or is the above example above the "correct" way to do it but to use a more accurate Sleep method? If so what method can I use?
Thanks in advance for your help.
Edit ---- Possible Idea...
DateTime timeAtStart = DateTime.Now;
int maxWaitTime = 15000;
while (true)
{
if (GetAsyncKeyState(System.Windows.Forms.Keys.Escape) != 0)
{
break;
}
if ((DateTime.Now - timeAtStart).TotalMilliseconds >= maxWaitTime)
{
break;
}
}
This doesn't use any sort of timer but looks like it could work, any suggestions?
Edit 2: The above works for me and now allows me to break the wait when escape is pressed. I have noticed the delay is more accurate than using Thread.Sleep too!
Consider reversing the concepts... instead of delaying it for a certain time, think about starting execution in a certain time, or when a key is pressed.
Start a Windows Forms timer with a tick handler which will kick off whatever you want to happen, and also a key event handler which will start it and stop the timer.
First sample is using Timer, ManuelResetEvent and Global Keyboard hook:
I did not include keyboard hook code because it's too large. You can find it here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace WindowsFormsApplication1
{
static class Program
{
private static System.Threading.Timer _timer;
private static ManualResetEvent _signal;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_signal = new ManualResetEvent(false);
_timer = new System.Threading.Timer(Timer_Signaled, null, 15000, 0);
_signal.WaitOne();
_signal.Reset();
Application.Run(new Form1());
}
private static void Timer_Signaled(object state)
{
_signal.Set();
}
}
}
When you hook to keyboard and ESC is pressed, simply call: _signal.Set(). This first sample is just to give you an idea.
Second sample:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
static class Program
{
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
int maxWaitTime = 15000;
int tc = System.Environment.TickCount;
while (true)
{
System.Threading.Thread.Sleep(1000);
if (System.Environment.TickCount - tc > maxWaitTime)
{
break;
}
if (GetAsyncKeyState(Keys.Escape) > 0)
{
break;
}
}
Application.Run(new Form1());
}
}
}
EDITED:
First sample is more reliable as keyboard hook use callback to inform which key was pressed. Second sample works like 'Pull' and it can happen not every key press will be collected.
Looking at your code, I'm assuming you're using Windows Forms for the UI.
There are many ways to solve your issue, but given the framework the easiest that comes to my mind is:
Blocking your UI (i.e. : this.Enabled = false)
Setting up a timer (i.e.: timer.Tick += ContinueUITimer();)
Setting up a keyboard handler (i.e.: this.KeyDown += ContinueUIKeyboard)
With the ContinueUI functions like this:
void ContinueUIXxx(...)
{
timer.Tick -= ContinueUITimer;
this.KeyDown -= ContinueUIKeyboard;
this.Enabled = true;
... whatever else in the continuation;
}

Categories