Because their is a lack of events in the k8061 i wrote a class (for VB) which makes de k8061 card event driven.
It has the following features:
-Throw events when changing digital inputs
-Throw events when a trigger has been reached for analog inputs
-Throw event when power is lost
-Throw event when disconnected
-SetDigitalChannelK(Channel) accepts channels higher than 8 and automatically set the first analog channel to the highest setting. SetDigitalChannelK(9) will set analog channel 0 to the highest setting
-Automaticcaly reconnect after disconnect
An analogIn threshold has the settings:
-thresholdName
-repeatCount =number of times events should be triggered
-repeatInterval = millisecs between repeat of events
-direction = Should event be triggerd if value rises above ‘thresholdValue’ then enter ‘HIGHER’. Should event be triggered if value drops ‘thresholdValue’ then enter ‘LOWER’. Or should event be triggered when it passes ‘thresholdValue’, then enter ‘LOWERHIGHER’
-passDuration = Time in msecs the threshold must be reached before an event is fired.
The class itself
Imports System.Timers
Public Class k8061
'**************************************************************************************************************************************
'**********************************************************************************
'**
'** This class is only tested with 1 card. Closedevice will close every device,
'** i think it will raise disconnect events in other cards.
'**
'** The class will scan the various inputs and will fire an event when a change
'** has been detected. Every analogIn port will fire 'on_AnalogInUpdate' events
'** to update e.g. an digitaldisplay. Every port can have thresholds which will
'** fire their own events.
'**
'** To have more digital outputs:
'** SetDigitalChannelK(Channel) accepts channels higher than 8 and
'** automatically set the first analog channel to the highest setting.
'** SetDigitalChannelK(9) will set analog channel 0 to the highest setting
'**
'** The class wil automatically reconnect after disconnecting.
'**
'** !!To use this class in your own application, you obviously have to remove
'** the 'Form1' links...!!
'**
'** Credits: Lars Bosboom
'**
'**********************************************************************************
'**********************************************************************************
Const EVENTINTERVAL = 10 'change to whatever you like(in milliseconds, Recommended <50)
Const RECONNECTINTERVAL = 1000 'in milliseconds
Const RECONNECT = True 'Set to 'true' if you want to automatically reconnect after disconnection
Public Event on_PowerChange()
Public Event on_Disconnect()
Public Event on_DigitalInChange(ByVal i As Short, ByVal state As Boolean)
Public Event on_AnalogInThresholdReached(ByVal name As String, ByVal i As Short, ByVal value As Integer)
Public Event on_AnalogInUpdate(ByVal i As Short, ByVal value As Integer)
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Private Declare Function OpenDevice Lib "k8061.dll" () As Integer
Private Declare Sub CloseDevices Lib "k8061.dll" ()
Private Declare Function ReadAnalogChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer) As Integer
Private Declare Function PowerGood Lib "k8061.dll" (ByVal CardAddress As Integer) As Boolean
Private Declare Function Connected Lib "k8061.dll" (ByVal CardAddress As Integer) As Boolean
Private Declare Sub ReadVersion Lib "k8061.dll" (ByVal CardAddress As Integer, ByRef Buffer As Integer)
Private Declare Sub ReadAllAnalog Lib "k8061.dll" (ByVal CardAddress As Integer, ByRef Buffer As Integer)
Private Declare Sub OutputAnalogChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer, ByVal Data As Integer)
Private Declare Sub OutputAllAnalog Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Buffer As Integer)
Private Declare Sub ClearAnalogChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer)
Private Declare Sub SetAllAnalog Lib "k8061.dll" (ByVal CardAddress As Integer)
Private Declare Sub ClearAllAnalog Lib "k8061.dll" (ByVal CardAddress As Integer)
Private Declare Sub SetAnalogChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer)
Private Declare Sub OutputAllDigital Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Data As Integer)
Private Declare Sub ClearDigitalChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer)
Private Declare Sub ClearAllDigital Lib "k8061.dll" (ByVal CardAddress As Integer)
Private Declare Sub SetDigitalChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer)
Private Declare Sub SetAllDigital Lib "k8061.dll" (ByVal CardAddress As Integer)
Private Declare Function ReadDigitalChannel Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Channel As Integer) As Boolean
Private Declare Function ReadAllDigital Lib "k8061.dll" (ByVal CardAddress As Integer) As Integer
Private Declare Sub OutputPWM Lib "k8061.dll" (ByVal CardAddress As Integer, ByVal Data As Integer)
Private Shared tickTimer As New System.Windows.Forms.Timer()
Private Shared reconnectTimer As New System.Windows.Forms.Timer()
Dim CardAddress As Integer = -4
Dim Power As Boolean
Dim AllDigital As Integer
Const LOWER = 2
Const HIGHER = 3
Const LOWERHIGHER = 1
Public AnalogIn(7) As AnalogInChannelClass
'Dim AnalogIn() As Collection
Dim firstPower As Boolean 'When connected without power, this will prevent triggering events for all ports
Structure AnalogInThreshold
Public thresholdValue As Integer
Public thresholdName As String
Public repeatCount As Integer 'number of times events should be triggered
Public repeatInterval As Integer 'millisecs between repeat of events
Public direction As Short 'Should event be triggerd if value rises above 'thresholdValue' then enter 'HIGHER'. Should
'event be triggered if value drops below 'thresholdValue' then enter 'LOWER'. Or should
'event be triggered when it passes 'thresholdValue', then enter 'LOWERHIGHER'
Public passDuration As Integer 'Time in msecs the threshold must be reached before an event is fired.
Public timeThresholdPassed As Integer
Public RepeatCountDone As Integer
End Structure
Public Class AnalogInChannelClass
Public value As Integer
Public rawValue As Integer
Public maximum As Integer = 1023
Public minimum As Integer
Public Thresholds(9) As AnalogInThreshold 'maximum of thresholds per port, change if you need to
End Class
Public Sub New()
tickTimer.Interval = EVENTINTERVAL
reconnectTimer.Interval = RECONNECTINTERVAL
AddHandler tickTimer.Tick, AddressOf tik
AddHandler reconnectTimer.Tick, AddressOf tryReconnect
'MsgBox("test" + Me.CardAddress.ToString)
Dim J As Integer
For J = 0 To 7
AnalogIn(J) = New AnalogInChannelClass
Next J
'-----------------------------------------------------------------------------------------------------------
' ----------------Example Definition for port 3---------------------------------------------------------------------
'-----------------------------------------------------------------------------------------------------------
Me.AnalogIn(3).minimum = 0 'change to whatever 0 volts would represent as a value
Me.AnalogIn(3).maximum = 100 'change to whatever 5-10 volts would represent as a value
Dim Thres As AnalogInThreshold 'LEAVE - One time needed for all thresholds
'ReDim Me.AnalogIn(3).Thresholds(2) 'number of total thresholds
'------Add a new threshold-------
Thres = New AnalogInThreshold()
Thres.thresholdValue = 10
Thres.thresholdName = "eerste threshold"
Thres.direction = LOWER 'See --> 'Structure AnalogInThreshold'
Thres.passDuration = 100 'Time in msecs the threshold must be reached before an event is fired.
Thres.repeatCount = 7 'number of times events should be triggered
Thres.repeatInterval = 600 'millisecs between repeat of events
Me.AnalogIn(3).Thresholds(0) = Thres 'change to appropriate port and increase Thressholds position
'--------------------------------
'------Add a new threshold-------
Thres = New AnalogInThreshold()
Thres.thresholdValue = 60
Thres.thresholdName = "de tweede threshold"
Thres.direction = HIGHER
Thres.passDuration = 4000
Thres.repeatCount = 3
Thres.repeatInterval = 1500
Me.AnalogIn(3).Thresholds(1) = Thres 'change to appropriate port and increase Thressholds position
'--------------------------------
'-----------------------------------------------------------------------------------------------------------
' ----------------End of definition for port 3-----------------------------------------------------------------
'-----------------------------------------------------------------------------------------------------------
End Sub
Private Sub tryReconnect(ByVal myObject As Object, ByVal myEventArgs As EventArgs)
If Me.Connect() > -1 Then 'succesfully reconnected
Form1.TextBox1.Text += "SUCCESFULLY RECONNECTED" + vbNewLine
reconnectTimer.Stop()
End If
End Sub
Private Function checkConnection() As Boolean
Dim ret As Boolean
ret = Connected(Me.CardAddress)
If (ret = False) Then
Form1.TextBox1.Text += "Connection lost. stop monitoring" + vbNewLine
Disconnect(True)
RaiseEvent on_Disconnect()
If (RECONNECT) Then
Form1.TextBox1.Text += "Try to reconnect" + vbNewLine
reconnectTimer.Start() 'start reconnecting
End If
Return False
End If
Return True
End Function
Public Function Connect() As Integer 'the dll will return -1(all cards connected) when not plugged in!!
Dim retaddress
If (Me.CardAddress > -1) Then 'already connected, after reconnect powergood is for a few milliseconds false, so dont retry
Return -1
End If
retaddress = OpenDevice()
If (retaddress > -1) Then
Me.CardAddress = retaddress
Me.Power = PowerGood(Me.CardAddress)
Me.AllDigital = ReadAllDigital(Me.CardAddress)
tickTimer.Start()
If (Me.Power = False) Then
Me.firstPower = True
Return -3
End If
End If
Return retaddress
End Function
Private Sub checkAnalogIn()
Dim Buffer(7) As Integer
ReadAllAnalog(Me.CardAddress, Buffer(0))
Dim port, I, x, y, convertedValue As Integer
Dim thrReached As Boolean
For port = 0 To 7
For I = 0 To Me.AnalogIn(port).Thresholds.Length - 1
thrReached = False
convertedValue = Me.AnalogIn(port).minimum + (Me.AnalogIn(port).maximum * Buffer(port) / 1023)
With Me.AnalogIn(port).Thresholds(I)
Select Case .direction
Case 3 'HIGHER
If (convertedValue > .thresholdValue) Then
'MsgBox("boven threshold")
thrReached = True
Else
.timeThresholdPassed = 0
End If
Case 2 'LOWER
If (convertedValue < .thresholdValue) Then
'MsgBox("onder threshold" + timeGetTime.ToString)
thrReached = True
Else
.timeThresholdPassed = 0
End If
Case 1 'LOWERHIGHER
x = convertedValue - .thresholdValue
y = Me.AnalogIn(port).value - .thresholdValue
thrReached = True
If ((x > 0 And y < 0) Or (x < 0 And y > 0)) Then
.timeThresholdPassed = 0
Form1.TextBox1.Text += "passed x = " + x.ToString + " y = " + y.ToString + vbNewLine
End If
End Select
If thrReached Then
If .timeThresholdPassed > 0 Then
If ((timeGetTime - .timeThresholdPassed) > .passDuration) Then 'duration before first event
If (.repeatCount > .RepeatCountDone) Then
If ((timeGetTime - .timeThresholdPassed - .passDuration) > (.repeatInterval * .RepeatCountDone)) Then
.RepeatCountDone = .RepeatCountDone + 1
RaiseEvent on_AnalogInThresholdReached(.thresholdName, port, convertedValue)
End If
End If
End If
Else
.timeThresholdPassed = timeGetTime
.RepeatCountDone = 0
If (.passDuration = 0) Then
RaiseEvent on_AnalogInThresholdReached(.thresholdName, port, convertedValue)
End If
End If
End If
End With
Next I
Me.AnalogIn(port).value = convertedValue
Me.AnalogIn(port).rawValue = Buffer(port)
RaiseEvent on_AnalogInUpdate(port, convertedValue)
Next port
End Sub
Private Function checkPower() As Boolean
Dim ret As Boolean
ret = PowerGood(Me.CardAddress)
If Not (ret = Me.Power) Then
If (checkConnection()) Then
Form1.TextBox1.Text += "checkpower" + Me.CardAddress.ToString + " ret= " + ret.ToString + " me.power= " + Me.Power.ToString + " connection=" + Connected(Me.CardAddress).ToString + vbNewLine
Me.Power = ret
If (Me.firstPower = True) Then 'if true this will prevent triggering events for all ports
Me.AllDigital = ReadAllDigital(Me.CardAddress)
'MsgBox(Me.AllDigital)
Me.firstPower = False
End If
RaiseEvent on_PowerChange()
End If
End If
Return ret
End Function
Private Sub checkDigitalIn()
Dim ret As Integer
' Dim dif As Integer
Dim nu As Short
Dim i As Short = 0
Dim state As Boolean
Dim dum As Integer
ret = ReadAllDigital(Me.CardAddress)
If (checkConnection()) Then 'hmm, seems double but checkConnection sometime wont trigger earlier on
If Not (ret = Me.AllDigital And (ret < 256 Or ret > -1)) Then
dum = Me.AllDigital
Me.AllDigital = ret
Form1.TextBox1.Text += (Me.AllDigital And 1).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 2) / 2).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 4) / 4).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 8) / 8).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 16) / 16).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 32) / 32).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 64) / 64).ToString
Form1.TextBox1.Text += (CShort(Me.AllDigital And 128) / 128).ToString + vbNewLine
While i < 8
nu = CShort(ret And (2 ^ i))
If (nu Xor (CShort(dum And (2 ^ i)))) Then
state = nu
RaiseEvent on_DigitalInChange(i + 1, state) 'returns number of port and state
End If
i = i + 1
End While
End If
End If
End Sub
Private Sub tik(ByVal myObject As Object, ByVal myEventArgs As EventArgs)
If (checkPower()) Then
checkDigitalIn()
checkAnalogIn()
End If
End Sub
Public Function Disconnect(ByVal clearAll As Boolean) As Boolean
If (Me.CardAddress < 0) Then
Return True
End If
tickTimer.Stop()
If (clearAll) Then
Me.ClearAllDigitalK()
Me.OutputPWMK(0)
Me.ClearAllAnalogK()
End If
CloseDevices() 'ALL devices will close!
If (Connected(Me.CardAddress) = True) Then
Return False
End If
Me.CardAddress = -4
Return True 'succesfull disconnect
End Function
Public Sub SetAllDigitalK()
SetAllDigital(Me.CardAddress)
End Sub
Public Sub ClearAllDigitalK()
ClearAllDigital(Me.CardAddress)
End Sub
Public Sub SetDigitalChannelK(ByVal i As Short)
If (i > 8) Then
Me.SetAnalogChannelK((i - 8))
End If
SetDigitalChannel(Me.CardAddress, i)
End Sub
Public Sub clearDigitalChannelK(ByVal i As Short)
ClearDigitalChannel(Me.CardAddress, i)
End Sub
Public Sub OutputPWMK(ByVal value As Integer)
OutputPWM(Me.CardAddress, value)
End Sub
Public Function ReadDigitalChannelK(ByVal i As Short) As Boolean
Return ReadDigitalChannel(Me.CardAddress, i)
End Function
Public Function ReadAnalogChannelK(ByVal i As Short) As Integer
Return ReadAnalogChannel(Me.CardAddress, i)
End Function
Public Function ConnectedK() As Integer
Return Connected(Me.CardAddress)
End Function
Public Sub OutputAllDigitalK(ByVal data As Integer)
OutputAllDigital(Me.CardAddress, data)
End Sub
Public Sub SetAnalogChannelK(ByVal i As Short)
SetAnalogChannel(Me.CardAddress, i)
End Sub
Public Sub ClearAllAnalogK()
ClearAllAnalog(Me.CardAddress)
End Sub
Public Sub SetAllAnalogK()
SetAllAnalog(Me.CardAddress)
End Sub
Public Sub ClearAnalogChannelK(ByVal i As Short)
ClearAnalogChannel(Me.CardAddress, i)
End Sub
Public Sub OutputAllAnalogK(ByVal buffer As Integer)
OutputAllAnalog(Me.CardAddress, buffer)
End Sub
Public Sub OutputAnalogChannelK(ByVal i As Short, ByVal Data As Integer)
OutputAnalogChannel(Me.CardAddress, i, Data)
End Sub
End Class
I only tested it on one card, to use it with more cards the code has to be changed.
Please let me know what you think of this code.