Search code examples
mysqlvb.netmodbus

Collecting data from PLC every 1 sec - would like to get the data when the data changes


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

Solution

  • 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).