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


Best Answer Nevyn, 21 September 2015 - 05:25 PM

It would be less processor intensive to use a timer to do this along with an interrupt which triggers on either a rising or falling edge.

 

So set up a timer which triggers every 100ms.  This would just toggle the LED.

 

In your interrupt handler for J1pin4 you would check the edge of the interrupt.  If it was a falling edge then you would enable the timer and return from the interrupt handler.  If the interrupt was generated on a rising edge then you would turn the timer off.

 

Hope that makes sense,

Mark

Go to the full post


  • Please log in to reply
6 replies to this topic

#1 WriterGuy

WriterGuy

    Member

  • Members
  • PipPip
  • 10 posts

Posted 16 September 2015 - 07:17 PM

Hello all,

 

I'm working on a project using the Netduino Plus 2. I am trying to run a series of tests on the components of a circuit board, and am looking to control each test using interrupts triggered by switches. In all, I have 6 tests (and subsequently 6 switches with 6 interrupts). 

 

Here's where my current issue lies:

 

I am having the Netduino light LED's upon successful completion of each test. If the test is unsuccessful, I blink the LED. My program enters the interrupt when the switch is flipped and lights (or flashes) the LED, but when I flip the switch back off, the LED remains lit (or stays flashing). Essentially, the LED behavior continues even after I turn off the switch to the test. 

 

A) I am wondering if I am not exiting the interrupt properly.

B) I am also wondering if my set up involving the blinking LED is the correct route to take, or if I have just simply set myself up for an endless loop.

The following is a sample of one of my interrupts. Any help would be much appreciated!

static void U1TestSwitch_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            J1pin3.Write(false);
            J1pin5.Write(false);
            J1pin7.Write(false);
            J1pin4.Read();

            if (J1pin4.Read() == true)
            {
                U1TLED.Write(true);
            }

            else if (J1pin4.Read() == false)
            {
                while (J1pin4.Read() == false)
                {
                    U1TLED.Write(true);
                    Thread.Sleep(100);
                    U1TLED.Write(false);
                    Thread.Sleep(100);

                    if (U1TestSwitch.Interrupt == Port.InterruptMode.InterruptEdgeLow)
                    {
                        break;
                    }

                }
            }

            if (U1TestSwitch.Interrupt == Port.InterruptMode.InterruptEdgeLow)
            {
                U1TLED.Write(false);
                U1TestSwitch.ClearInterrupt();
            }
            
        }




#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 18 September 2015 - 07:28 AM

Hi WriterGuy,

It's hard to see exactly what's going on here without the full code, but here are a few troubleshooting tips:

1. The data2 parameter passed into the interrupt function will hold the high/low state of the line when the interrupt is generated. When you're checking the InterruptMode...are you meaning to check the interrupt _state_?

2. Generally speaking, it's best to process interrupts and exit interrupt handlers as quickly as possible. Further interrupts can't be fired while you're in your handler, and if a lot of interrupts happen then the interrupt event queue will overflow and you'll lose interrupts.

Does that help get you on the right path?

Chris

#3 WriterGuy

WriterGuy

    Member

  • Members
  • PipPip
  • 10 posts

Posted 18 September 2015 - 11:32 AM

Thanks for the reply Chris!

 

1. Indeed I am looking to check the interrupt state. I am wanting to have the interrupt end and return to main whenever the I turn the switch associated with that interrupt off. In my readings I haven't ever come across how to check the interrupt state.

 

2. The interrupts are designed to run the tests. They are simple "Are they working or are they not" type tests, so it should be as simple as flipping the switch, checking if the LED is lit or flashing, and then flipping the switch back off. 



#4 JoopC

JoopC

    Advanced Member

  • Members
  • PipPipPip
  • 148 posts

Posted 19 September 2015 - 07:12 AM

Your example can not work properly.
Here is a good example snippet in VB (give you a idea) how to work with interrups AND READ() together, as Chris say, go as quickly as possible out of a intterupt, so make another thread. In my believe the on_interrupt occupy all the interrups in other threads until leave. This example works and tested.

COPY PASTE example in a new class sheet and see:

Imports System
Imports Microsoft.SPOT

'created by JoopC and G Brander
'there are many ideas implemented from other programmers.
'so credits to all of you.

#Region "Class, Electric board PulseMeter or TCRT5000 in a seperate Thread"


'change to TRUE to debug
#Const DEBUG = False



Namespace S0PulseMeter

Public Class PulseMeter

'energy consumption meter with S0 pulse output
Private _dPin As Cpu.Pin
Private _interruptPort As InterruptPort
Private _PulsesInKWH As Integer = 0
Private _intPulseCount As Integer = 0
Private _intWattNow As Integer = 0
Private _pulsesToWatt As Double = 0.0R
Private _PulsesToKW As Double = 0.0R
Private _PinOnWrite As strcPinOnWrite
Private _maximumCapacity As Integer
Private _dtStartTime As DateTime = DateTime.Now.AddHours(-1)
Private _returnToZeroDelayTicks As Long
Private _timeSpanZeroWattNow As Long = DateTime.Now.Ticks
Private _ID As Integer = -1
Private _unit As enumUnit
Private _resetToStartValueOnNewDay As Boolean
Private _startValue As Double

'new
Private _TotalPulses As Integer


'watermeter support
Private _isTCRT5000 As Boolean
Private _receivePulse As Boolean

Private PulseThread As Thread = Nothing

Public Sub Start()
PulseThread.Start()

End Sub

Public Sub New()
Me._PulsesInKWH = 0
Me._pulsesToWatt = 0
Me._PulsesToKW = 0
End Sub

Public Sub New(
ByVal dPin As Cpu.Pin,
ByVal Pulses As Integer,
ByVal PinOnWrite As strcPinOnWrite,
ByVal capacity As Integer,
ByVal returnToZeroDelayTicks As Long,
ByVal ID As Integer,
ByVal unit As enumUnit,
ByVal resetToStartValueOnNewDay As Boolean,
ByVal StartValue As Double,
ByVal TCRT5000 As Boolean)

PulseThread = New Thread(AddressOf InterruptPortThread)

Me._PulsesInKWH = CInt((3600 / Pulses) * 1000)
Me._pulsesToWatt = (1000 / Pulses)


Me._PulsesToKW = Pulses

Me._PinOnWrite = PinOnWrite
Me._dPin = dPin
Me._maximumCapacity = capacity
Me._returnToZeroDelayTicks = returnToZeroDelayTicks
Me._ID = ID
Me._unit = unit
Me._resetToStartValueOnNewDay = resetToStartValueOnNewDay
Me._startValue = StartValue
Me._isTCRT5000 = TCRT5000

End Sub


''' <summary>
'''
''' </summary>
''' <param name="data1"></param>
''' <param name="data2"></param>
''' <param name="time"></param>
''' <remarks></remarks>
Private Sub interruptTCRT5000(data1 As UInteger, data2 As UInteger, time As Date)

Me._interruptPort.DisableInterrupt()
Me._receivePulse = True

#If DEBUG Then
Debug.Print("Pulse Detected " & DateTime.Now.ToString)
#End If

Thread.Sleep(10)

End Sub



Private Sub InterruptPortThread()

Me._interruptPort = New InterruptPort(Me._dPin, False, Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeHigh)

If Me._isTCRT5000 Then

'watermeter
AddHandler Me._interruptPort.OnInterrupt, AddressOf interruptTCRT5000

'max time to wait if a pulse is received
Const cnstWAITtime As Integer = 1800

Do While True

If Me._receivePulse AndAlso Not blnExclusiveAction AndAlso Me._interruptPort.Read() Then

#If DEBUG Then
Debug.Print("TCRT5000 Pulse written & reset interrupt " & DateTime.Now.ToString)
#End If

functions.WritePin(Me._PinOnWrite, True)

Me._timeSpanZeroWattNow = DateTime.Now.Ticks + Me._returnToZeroDelayTicks
Me._intPulseCount += 1
Me._intWattNow = CInt(Me._PulsesInKWH / ((DateTime.Now.Ticks - Me._dtStartTime.Ticks) / TimeSpan.TicksPerSecond))

Me._dtStartTime = DateTime.Now

Thread.Sleep(40)

functions.WritePin(Me._PinOnWrite, False)

'reset pulse
Me._receivePulse = False

Me._interruptPort.EnableInterrupt()
Me._interruptPort.ClearInterrupt()

End If

#If DEBUG Then
Debug.Print("Sleep " & DateTime.Now.ToString)
#End If

Thread.Sleep(cnstWAITtime)
Loop

Else

AddHandler Me._interruptPort.OnInterrupt, AddressOf interrupt_soPulseMeter

End If

End Sub


''' <summary>
'''
''' </summary>
''' <param name="data1"></param>
''' <param name="data2"></param>
''' <param name="time"></param>
''' <remarks></remarks>
Private Sub interrupt_soPulseMeter(data1 As UInteger, data2 As UInteger, time As Date)

' * To prevent stray voltage pulses *
'' ******* ******
'' * If your system has a higher standby power usage than 10W *
'' * adjust the cnstMinWattageToDetect as needed *

Const cnstMinWattageToDetect As Integer = 10

Try

functions.WritePin(Me._PinOnWrite, True)

Dim intWattage As Integer = CInt(Me._PulsesInKWH / ((DateTime.Now.Ticks - Me._dtStartTime.Ticks) / TimeSpan.TicksPerSecond))

If intWattage > cnstMinWattageToDetect AndAlso intWattage < Me._maximumCapacity Then

Me._timeSpanZeroWattNow = DateTime.Now.Ticks + Me._returnToZeroDelayTicks
Me._intPulseCount += 1
Me._intWattNow = intWattage

End If
_dtStartTime = DateTime.Now

Thread.Sleep(40)

functions.WritePin(Me._PinOnWrite, False)

Me._interruptPort.ClearInterrupt()

If blnExclusiveAction Then
Me._interruptPort.DisableInterrupt()
SyncLock dummySPIsyncLock

End SyncLock
Me._interruptPort.EnableInterrupt()
End If

Catch ex As Exception

End Try

End Sub

Public Sub clear()
Me._intPulseCount = 0
End Sub

Public ReadOnly Property ID As Integer
Get
Return Me._ID
End Get
End Property

Public ReadOnly Property resetToStartValueOnNewDay As Boolean
Get
Return Me._resetToStartValueOnNewDay
End Get
End Property

Public ReadOnly Property StartValue As Double
Get
Return Me._startValue
End Get
End Property

Public ReadOnly Property unit As enumUnit
Get
Return Me._unit
End Get
End Property

Public Property Pulses As Integer
Set(ByVal value As Integer)
Me._intPulseCount = If(value < 0, 0, value)
End Set
Get
Return Me._intPulseCount
End Get
End Property

Public Property WattageNow As Integer
Set(ByVal value As Integer)
Me._intWattNow = If(value < 0, 0, value)
End Set
Get
If DateTime.Now.Ticks > Me._timeSpanZeroWattNow Then
Me._intWattNow = 0
End If

Return Me._intWattNow
End Get
End Property

Public Property KWH As Double
Set(ByVal value As Double)
Me._intPulseCount = If(value < 0, 0, Integer.Parse((Me._PulsesToKW * value).ToString("F0")))
End Set
Get
Return Me._intPulseCount * Me._pulsesToWatt
End Get
End Property


Public Property totalPulses As Integer
Set(ByVal value As Integer)
Me._TotalPulses = value
End Set

Get
Return Me._TotalPulses
End Get
End Property


Public Property totalKWH As Double
Set(ByVal value As Double)
Me._TotalPulses = If(value < 0, 0, Integer.Parse((Me._PulsesToKW * value).ToString("F0")))
End Set
Get
Return Me._TotalPulses * Me._pulsesToWatt
End Get
End Property

Public Sub resetZeroDelay()
Me._timeSpanZeroWattNow = DateTime.Now.Ticks + Me._returnToZeroDelayTicks
End Sub

End Class

End Namespace

#End Region

#5 WriterGuy

WriterGuy

    Member

  • Members
  • PipPip
  • 10 posts

Posted 21 September 2015 - 03:54 PM

Thanks for all the feedback guys! I'm starting to get on the right track.

 

I still have a question about my while loop though. Basically, in my interrupt, if J1pin4 reads true, U1TLED is set to true and the LED will light. However, I am looking to continuously blink the LED if false is read at J1pin4. I figured a while loop would be best to use for this, but I'm not sure if the way I have it set up is just going to put me in a continuous loop. 

 else if (J1pin4.Read() == false)
            {
                while (J1pin4.Read() == false)
                {
                    U1TLED.Write(true);
                    Thread.Sleep(100);
                    U1TLED.Write(false);
                    Thread.Sleep(100);
 
                    if (U1TestSwitch.Interrupt == Port.InterruptMode.InterruptEdgeLow)
                    {
                        break;
                    }
 
                }
            }


#6 Nevyn

Nevyn

    Advanced Member

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

Posted 21 September 2015 - 05:25 PM   Best Answer

It would be less processor intensive to use a timer to do this along with an interrupt which triggers on either a rising or falling edge.

 

So set up a timer which triggers every 100ms.  This would just toggle the LED.

 

In your interrupt handler for J1pin4 you would check the edge of the interrupt.  If it was a falling edge then you would enable the timer and return from the interrupt handler.  If the interrupt was generated on a rising edge then you would turn the timer off.

 

Hope that makes sense,

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


#7 WriterGuy

WriterGuy

    Member

  • Members
  • PipPip
  • 10 posts

Posted 21 September 2015 - 07:04 PM

Nevyn,

 

Thanks for the idea. I want to try this, but my program doesn't recognize Timers. Apparently, my VS2010 does not have system.dll referenced and I can't find the file to add it. Is there a way to perform the timer task without using the Timers namespace?






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.