I am currently collecting data from my PLC with easyModbus (using Visual Basic) every 1 second with a timer and later I want to insert data to a database. My goal is to only refresh data in my program when a value changes inside of the PLC.
For example: I have 4 LEDs, 1-green 2-yellow 3-red 4-blue, and I have a timer which measures the elapsed time from when the red light comes on to when it turns of.
I want to log the time data to a database....when the error happened...when the error if fixed. But with my 1 sec refresh it is writing my data every 1 sec and I need it to only write the data when it changed...and I also don't want to ask the PLC every single second because I don't need to.
Public Sub Refresh_btn_Click() Handles Refresh_btn.Click
Dim ComError = 0 'Set comm error flag to 0
Dim Ipaddress As String
Ipaddress = "127.0.0.1"
Dim Portaddress As String
Portaddress = "502"
Dim ModbusClient As EasyModbus.ModbusClient = New EasyModbus.ModbusClient(Ipaddress, Portaddress) 'Ip address and port Text box = Ip on form
Try
ModbusClient.Connect() 'Connect to PLC
Catch ex As Exception 'What to do when error occurs
Status_lbl.BackColor = Color.Red
Status_lbl.ForeColor = Color.White
Status_lbl.Text = "Error!"
ComError = 1 'Set comm error flag to 1
End Try
If ComError = 0 Then
Status_lbl.BackColor = Color.Green
Status_lbl.ForeColor = Color.White
Status_lbl.Text = "No Error!"
'First line Andon
Dim Registers As Integer()
Registers = ModbusClient.ReadHoldingRegisters(0, 10)
'Indexing Registers starting with null
If Registers(0) = 0 Then
GreenSIGN.BackColor = Color.LightGray
YellowSIGN.BackColor = Color.LightGray
RedSIGN.BackColor = Color.LightGray
BlueSIGN.BackColor = Color.LightGray
End If
If Registers(0) = 1 Then
GreenSIGN.BackColor = Color.Green
Else
GreenSIGN.BackColor = Color.LightGray
End If
If Registers(0) = 2 Then
YellowSIGN.BackColor = Color.Yellow
Else
YellowSIGN.BackColor = Color.LightGray
End If
If Registers(0) = 3 Then
RedSIGN.BackColor = Color.Red
Else
RedSIGN.BackColor = Color.LightGray
End If
If Registers(0) = 4 Then
BlueSIGN.BackColor = Color.Blue
Else
BlueSIGN.BackColor = Color.LightGray
End If
End If
ModbusClient.Disconnect()
'Timer for downtime Static Start-Stop
Static start_time As DateTime = Now
Static stop_time As DateTime = Now
Static start_time2 As DateTime = Now
Static stop_time2 As DateTime = Now
Dim elapsed_time As TimeSpan
'Only Red Andon
'If for Red andon For Line XXX
If RedSIGN.BackColor = Color.Red Then
stop_time = Now
elapsed_time = stop_time.Subtract(start_time)
lbl_elapsed_red.Text = elapsed_time.ToString("hh\:mm\:ss")
Else
lbl_elapsed_red.Text = "Ok"
start_time = Now
End If
'Only Blue Andon
'If for Blue andon For Line XXX
If BlueSIGN.BackColor = Color.Blue Then
stop_time2 = Now
elapsed_time = stop_time2.Subtract(start_time2)
lbl_elapsed_blue.Text = elapsed_time.ToString("hh\:mm\:ss")
Else
lbl_elapsed_blue.Text = "Ok"
start_time2 = Now
End If
'Connectin MySQL
'Try
' Dim SQL As String 'SQL Command String
' Dim objCmd As New MySqlCommand 'Command
' 'Connection String to the SQL Database
' Dim Con = New MySqlConnection("server=127.0.0.1;user id=root;database=andon")
' 'SQL Statement - All values must be set for the table
' SQL = "INSERT INTO test_andon VALUES ('" & Now.ToString("yyyy/MM/dd") & "', '" & Now.ToString("HH:mm:ss") & "','" & "@dummy" & "', '" & Now.ToString("start_time2") & "', '" & "@dummy" & "', '" & "@dummy" & "')"
' Con.Open() 'Open the database connection
' objCmd = New MySqlCommand(SQL, Con) 'Set the command
' objCmd.ExecuteNonQuery() 'Execute the SQL command
' Con.Close() 'Close the database connection
'Catch ex As Exception 'What to do when an error occurs
' Status_lbl.BackColor = Color.Red
' Status_lbl.ForeColor = Color.White
' Status_lbl.Text = "Database Error Blue vége!"
'End Try
End Sub
'Timer reping
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Timer1.Interval = 100
Timer1.Enabled = True
Call Sub() Refresh_btn_Click()
End Sub
You can store the state of the red light and check if the new value is different from the old value. If it is, then write to the database and update the old value, otherwise do nothing.
For example, pretend that the incoming value related to the red light is r(t)
:
Imports System.Timers
Module Module1
Dim t As Integer = 0
Dim r() As Integer = {0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1}
Dim prevValue As Integer = Integer.MinValue
Sub tock(sender As Object, e As ElapsedEventArgs)
Dim val = r(t)
Console.Write(val.ToString() & " ")
If val <> prevValue Then
Console.WriteLine("Write to database.")
prevValue = val
Else
Console.WriteLine("Do nothing.")
End If
t = (t + 1) Mod r.Length
End Sub
Sub Main()
Dim tim As New Timers.Timer With {.Interval = 1000, .AutoReset = True}
AddHandler tim.Elapsed, AddressOf tock
tim.Start()
Console.WriteLine("Tocking... press enter to quit.")
Console.ReadLine()
tim.Stop()
tim.Dispose()
End Sub
End Module
Outputs:
Tocking... press enter to quit.
0 Write to database.
1 Write to database.
1 Do nothing.
1 Do nothing.
1 Do nothing.
0 Write to database.
0 Do nothing.
0 Do nothing.
0 Do nothing.
0 Do nothing.
1 Write to database.
0 Write to database.
1 Write to database.
1 Do nothing.
[Carries on until enter is pressed.]
Notice that the first value makes a write-to-database because prevValue
was initialised to a value which r(t)
will never have. After that, write-to-database only happens when r(t)
<> r(t-1)
.