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