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

Interrupt stops working after a while?


  • Please log in to reply
14 replies to this topic

#1 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 24 July 2015 - 02:42 AM

I have a ND Plus 2 that has a PIR sensor attached.

Everytime the PIR is triggered by movement I log the bit into Azure.

I have a heartbeat bit I loggin to Azure every 15 minutes to tell me the gateway is alive.

I have been running this code on my ND Plus 2 for many months. 24 X 7 without issue.

As the weeks wear on, my PIR data stops getting logged to Azure.

I reboot the board and things run fine for weeks before I have to reboot.

Then and they run fine for a week before I have to reboot.

Now I have to reboot every day and then the PIR only logs for a few hours.

 

My HeartBeat interupt keeps on logging to Azure.

So my thought is that the PIR interupt is not firing.

 

But I have no idea, I am new at this fun area of micro boards and IOT.

Any idea on what might be happening, or how to improve my code to make it more robust?

Thank you.

public class Program
{
	#region Properties

	private static string SubLocationID = "Gateway";

	private static int HeartBeatTimerPeriod = 15;
	private static Timer HeartBeatTimer = null;
	private static TimerCallback TimerCallback = null;
	private static DateTime LastMotionDetectedTime;

	private static OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
	private static bool MotionDetected = false;
	private static InterruptPort PIRInterupt;
	private static string MACAddress;
	private static InterruptPort sdCardStatusPort;

	#endregion

	#region Methods

	public static void Main()
	{

		if (Program.GetIPAddressAndSetTime(out Program.MACAddress))
		{
			Program.AddData(Program.MACAddress, PIRLocal.MessageType.START);

			Program.TimerCallback = new TimerCallback(HeartBeatTimerInterrupt);
			Program.HeartBeatTimer = new Timer(Program.TimerCallback, null, 0, Program.HeartBeatTimerPeriod * 60000);

			//set the interupts after we get an ip address and time.
			PIRInterupt = new InterruptPort(Pins.GPIO_PIN_D8, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
			PIRInterupt.OnInterrupt += PIRInterupt_OnInterrupt;

			NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);
			NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);

			while (true)
			{
				if (MotionDetected)
				{
					Program.MotionDetected = false; //turn this off.
					Program.Blink(1, 75);
					Program.AddData(Program.MACAddress, PIRLocal.MessageType.PIR);
				}
				Thread.Sleep(500);
			}
		}
	}

	private static bool GetIPAddressAndSetTime(out string macAddress)
	{
		while (!Network.GetIPAddress(out macAddress)) { }

		if (NTP.SetUTCTimeFromNtpServer())
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	private static void AddData(string macAddress, PIRLocal.MessageType messageType)
	{
		WebClient wc = new WebClient("http://xxxxxxx.azurewebsites.net/api/values", "Post");
		PIRLocal sd = new PIRLocal(macAddress, Program.SubLocationID, messageType);
		wc.Data = sd.ToJson();
		wc.Submit();

		Debug.Print(wc.ResponseStatusCode);
		Debug.Print(wc.ResponseStatusDescription);
		Debug.Print(wc.Data);
	}

	#endregion

	#region Interupts

	private static void HeartBeatTimerInterrupt(object state)
	{
		Program.AddData(Program.MACAddress, PIRLocal.MessageType.HB);
	}

	static void PIRInterupt_OnInterrupt(uint data1, uint data2, DateTime time)
	{
		Program.MotionDetected = true;
		Debug.Print(data1.ToString() + " - " + data2.ToString() + " - " + time.AddHours(-6).ToString());
		//bool pin = pirInterupt.Read();
	}

	static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
	{
		//Program.GetIPAddressAndSetTime();
		Program.AddData(Program.MACAddress, PIRLocal.MessageType.NetworkAddressChanged);

	}

	static void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
	{
		Program.GetIPAddressAndSetTime(out Program.MACAddress);
		Program.AddData(Program.MACAddress, PIRLocal.MessageType.NetworkAvailabilityChanged);
	}

	#endregion
}



#2 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 25 July 2015 - 02:17 AM

Chris, can you take a look at this? Please.

#3 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 25 July 2015 - 06:51 AM

Just looking through the code, I'm wondering if you are leaking memory.

 

Have you tried logging the amount of available memory to Azure / Debug.Print.

 

I'd also look at making sure that you dispose of the web client object explicitly or maybe try wrapping a using around it to try and dispose of it straight away.  Another option on this would be to look at making the web client static and look at opening and  closing connections rather than making a new object every time.

 

None of this is guaranteed to solve the  problem but these are the areas I'd have a look at.

 

Hope this helps,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#4 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 25 July 2015 - 07:45 PM

Mark, those are some good ideas.

Thank you for the suggestions. I will put some of them into action.

Memory leak would explain it, except for the fact that the 15 min heartbeat still fires and logs to azure?

Still a good idea to tighten it up though.

Terrence

#5 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 26 July 2015 - 09:30 AM

Something I've just remembered, Timers run in their own threads.  So you may have problems with the main thread but not the timer thread.

 

Also, you say the Timer is an interrupt but it is not an interrupt in the same sense as the PIR.  You will be executing different paths through NETMF.

 

Have you though about wrapping the while loop in an exception handler?

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#6 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 26 July 2015 - 06:11 PM

>>Have you though about wrapping the while loop in an exception handler?

Well it takes about a week to get reach the error state. I can't keep the device connected to my machine that long to "catch" the error. I guess I could write it to the sd card.

Is that what you were thinking?

I am open for lots of ideas.

Thanks for your thoughts on this.

#7 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 26 July 2015 - 07:31 PM

I'd probably look at doing two things:

  • Use an output pin to indicate if an exception is caught
  • Try writing to an SD Card

I'd write to the pin first and then the SD card.  I'd do it this way to try and minimise any calls into the framework in case it was a memory issue.  So if the exception pin is high then we would know we have caught an exception even if nothing was logged to the SD card.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#8 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 27 July 2015 - 06:27 PM

Terrence--also, if you have an extra older PC sitting around...

You can install the Netduino drivers on it, run MFDeploy and connect to your board (F5).

And then you'll get the Debug.Print output.

If you can whittle your code down to a dozen lines or so (while still reproducing the error), we can help dig in and diagnose further. I know that this is an "after a long time" error so that might not be feasible--but we'd like to find a way to keep you running and running... :)

Chris

P.S. Thanks Nevyn for all your help here!

#9 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 28 July 2015 - 09:48 PM

Thanks Chris and Nevyn

 

Ok, so I put a Debug.GC(true) in my loop to fire if the PIR fired.  I restarted the board on Sunday and the last PIR hit was this morning at 9:00 am CST.  So it lasted about 2 days this time.  The 15 minute timer heartbeat messages are still getting sent an logged in Azure.

 

I am going to remove the GC in the PIR and add it to the timer loop....but that doesn't make sense.  Obviously there is no memory issue because the timer keeps firing and sending data to Azure.

 

I will attempt to catch an exception and write it to the SD card.

 

What do you think about the fact the 15 min timer keeps on working, but the PIR does not?



#10 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 29 July 2015 - 05:37 AM

Did you get any statistics out of the GC ?  Did it show the memory reducing?

 

What is the frequency of the PIR interrupts?  Could they be overwhelming the framework?

 

Can you trigger the fault more quickly by generating a large number of PIR interrupts in a shorter space of time?  If the system faults at 1,000 interrupts then can you generate those in say 2-3 hours instead of days/weeks.  I'm not thinking generate the interrupts really quickly - i.e. seconds, but say instead of having 1 hour between interrupts have say 5 seconds.

 

Could you replace the PIR with something like a 555 timer to simulate the interrupt at a higher frequency?

 

As for the reason the PIR stops, I'd probably start to investigate how threads work in NETMF as there are two threads at work here, one for the timer and one for the main loop running the PIR.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#11 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 29 July 2015 - 01:55 PM

Mark thanks for hanging in here with me on this problem.

 

I am a novice so please bear with me.

 

The Debug.GC(true) returns the amount of memory, and after I clear it each time it returns the same amount.

 

>>Frequency of PIR. 

Well sometimes its 2-3 per hour, but sometimes its 80-90, so I wouldn't think that was overwhelming the framework, would you?

 

>>Auto generating a bunch over a couple of hours to force the issue is a great idea.

 

>>555 Timer?

I will look into that.

 

Thank you again for your thoughts.



#12 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 29 July 2015 - 05:02 PM

I would not have thought that 80-90 interrupts per hour would be an issue but I wonder what would happen if they all arrived in the same second.

 

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#13 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 30 July 2015 - 09:06 PM

I am going to try that out.

 

I will do 100 in a second to see if it melts.

I will do 1 per second so I should get an error in a few hours I hope.

I will report back.



#14 Terrence

Terrence

    Member

  • Members
  • PipPip
  • 24 posts

Posted 06 August 2015 - 10:18 PM

Nevyn, Something has come up that is taking my attention from this project.  I hope to get back to it soon, and I hope you will read what my findings are. 

 

Thank you for keeping up with my posts.

 

Terrence



#15 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 07 August 2015 - 06:00 AM

Nevyn, Something has come up that is taking my attention from this project.  I hope to get back to it soon, and I hope you will read what my findings are. 

 

Thank you for keeping up with my posts.

Not a problem, would be nice to know what the final answer is :)

Regards,

Mark


To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter





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.