Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - bachphi

Pages: 1 2 3 [4] 5 6
46
Open Discussion / The search for a near perfect FSW.
« on: August 03, 2018, 08:25:38 PM »
FileSystemWatcher (FSW) is pretty useful to monitor a certain folder for new file creation, a text file that usually contains some result data. The file is processed by first parsing its content, next send its parsed data on to a SQL DB and finally move the file to an archived folder.

The key here is to know when process of file creation is complete. Most solutions are either relying on regular interval timer check or use several of FSW notify filters ( CreationTime,  FileName,  LastWrite,  Size )  to trigger event and then trying to open the file to check for its completion status. This approach is fine for low rate of file creation, but if there's a lot of files created in a short period of time, buffer overflow and missing file watching can occur.

FSW use a limited & non-paged memory and therefore long file name, deep level of sub directories, filter can all affect its performance. Increase the InternalBufferSize can help but MS only recommend its maximum size of 64KB.

Code: [Select]
Private Sub FileWatcher()
        Dim fsw As New FileSystemWatcher With {
            .Path = sourceDir,                               
            .InternalBufferSize = 65536,
            .IncludeSubdirectories = True,
            .Filter = "*.DAT",
            .NotifyFilter = (NotifyFilters.LastWrite)
            }
        AddHandler fsw.Changed, New FileSystemEventHandler(AddressOf OnChanged)
        fsw.EnableRaisingEvents = True
 End Sub

Perhaps, the most logical choice is the LastWrite notify filter. Oddly enough, LastWrite will actually trigger events twice, it is the second trigger mark the end of file writing and so it's good time to open the file to parse its content.
Code: [Select]
Private _fileCreated As Boolean = False
Private Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs)
        If _fileCreated Then                     'catching the second trigger event
             ParseFileContent(e.FullPath)
       'End If
        _fileCreated = Not _fileCreated
End Sub

The next logical one is the Size NotifyFilter, it trigger only once and appear to be at the end of file writing. I added the while loop for self assurance, may not needed:

Code: [Select]
Private Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs)
        Dim fileSize As Long = 0
        Dim currentFile As New FileInfo(e.FullPath)
        While Not (FileIsReady(e.FullPath))
            fileSize = currentFile.Length
            Thread.Sleep(25)
            currentFile.Refresh()
        End While
        ParseFileContent(e.FullPath)
End Sub
Private Function FileIsReady(ByVal path As String) As Boolean
        Try
            Using file = System.IO.File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
                Return True
            End Using
        Catch __unusedIOException1__ As IOException
            Return False
        End Try
End Function

47
Here is a very useful routine for your Compact/ControlLogix program.  just import it in.


48
Open Discussion / FactoryTalk View Studio v10
« on: June 21, 2018, 04:04:07 PM »
I have not touched the FTV  for a number of years ( thanks to Archie), but recently I ran into a PVP using v5.
I seemed to recall that starting from v5, v5.1  one can convert the MER file back to APA, so that was a big improvement from v4 and prior.
But then Rockwell introduced V6 and 64bit, and since then it's been either nightmare or a lot of hassle trying to find a 32 bit machine with FTV and then try to convert/export to the 64 bit.

To my surprise, v10 now can convert 32bit apa or 32bit mer file without the need of a 32 bit machine. The download size is huge  over 2.5GB, but the software seemed to run much faster than my recollection.

However, the v5/v5.1/v6 mer file that it produce will not be able to convert back to apa file.

49
Open Discussion / ControlLogixNET
« on: June 14, 2018, 01:43:56 PM »
I came across this ControlLogixNET, it is an open source project that claims to "interface with Allen-Bradley ControlLogix, CompactLogix, and MicroLogix PLC's" and "also tested to work on Mono!!!!".

Other than that, there is not much of info on how to and a lot of unanswered questions.

Anyway, since it is depends on EIPNET, I downloaded EIPNET and compiled it to get EIPNET.dll.
Next re-add references ( EIPNET, ICommon) in ControlLogixNet project, build it.
Next re-add references( EIPNET, ICommon,ControlLogixNET)in all projects of the Examples folder, build it.
Next , change the Startup solution to a project like SimpleOperations.
Change IP address and path to match, in my case it's a compactlogix so path is just 0.
Run it and read a tag.


50
Tips & Tricks / Passwording the Keypad of the BasicLabel
« on: June 08, 2018, 10:45:44 PM »
In case you want to restrict the access of the keypad, a modification to the OnClick event is needed.
Code: [Select]
Protected Overrides Sub OnClick(e As System.EventArgs)
        MyBase.OnClick(e)
        ReadUserInfo()

        If m_PLCAddressKeypad IsNot Nothing AndAlso (String.Compare(m_PLCAddressKeypad, "") <> 0) And Enabled Then
            Dim PassCodeKeypad As New MfgControl.AdvancedHMI.Controls.AlphaKeyboard3(m_KeypadWidth) With {
                .PasswordChar = True,
                .ForeColor = Color.Red,
                .Text = "ENTER PASSCODE"
            }
            PassCodeKeypad.ShowDialog()
            'If PassCodeKeypad.Value <> "1234" Then
            If PassCodeKeypad.Value <> Password Then
                MsgBox("INVALID PASS CODE!")
                Exit Sub
            End If

            ActivateKeypad()
        End If
    End Sub

And if you do not want to use the hardcoded password, but rather read from an xml file then:

Code: [Select]
    Dim Password As String
    Private Sub ReadUserInfo()
        'Dim UserName As String
        Dim doc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
        Dim filePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Application.ExecutablePath), "Credential.xml")

        doc.Load(filePath)
        For Each m_node As System.Xml.XmlNode In doc.SelectNodes("/passwordlist/User")
            'UserName = m_node.Item("UserName").InnerText
            Password = m_node.Item("Password").InnerText
        Next
    End Sub

51
There comes a time that one might need to log values or simply recording alarm messages.
The original code is from Archie, I just corrected a few minor errors and put it here for the convenience of searching

1. Close out all open forms
2. Right click AdvancedHMIControls\PurchasedControls folder and Add Existing Item
   Select MessageDisplayByValue.vb from the Controls folder

3. Rename the file to MessageDisplayByValueWithLogging.vb and answer NO to the dialog box

4. Open & Edit the line to: Public Class MessageDisplayByValueWithLogging

5. Add 2 new properties into the Properties Region
Code: [Select]
    Private m_LogFile As String = ""
    Public Property LogFile As String
        Get
            Return m_LogFile
        End Get
        Set(value As String)
            m_LogFile = value
        End Set
    End Property

    Private m_DaysToKeep As Integer = 10
    Public Property LogFileDaysToKeep As Integer
        Get
            Return m_DaysToKeep
        End Get
        Set(value As Integer)
            m_DaysToKeep = value
        End Set
    End Property

6. And Add an event into the Event Region
Code: [Select]
Protected Overrides Sub OnTextChanged(e As System.EventArgs)
        MyBase.OnTextChanged(e)

        If m_LogFile <> "" Then
            System.IO.Directory.CreateDirectory(m_LogFile)
            If Me.Text <> "" Then
                Dim sw As New System.IO.StreamWriter(m_LogFile & "\" & m_LogFile & Format(Now(), "yyyyMMdd") & ".txt", True)
                sw.WriteLine(DateString & "     " & TimeOfDay & "     " & MyBase.Text)
                sw.Close()
            End If

            For Each file As IO.FileInfo In New IO.DirectoryInfo(LogFile).GetFiles("*.txt")
                If (Now - file.CreationTime).Days >= m_DaysToKeep Then file.Delete()
            Next

        End If
End Sub

7.  Build your solution

52
Open Discussion / Modbus with Micrologix 1400
« on: May 29, 2018, 10:42:14 PM »
Besides the regular SerialDF1 & EthernetIPforSLCMicro communication, Micrologix 1400 also offer Modbus RTU & modbus TCP. It's very nice to have this flexibility. I am not sure why Rockwell did not integrate modbus into their Compactlogix line.

First, Enable it in the channel configuration


Once it enabled, Channel 1 modbus tab will appear and here you can config your file number accordingly


 
Dont forget to recycle power to ML1400. Next some codings:

Code: [Select]
Imports AdvancedHMIDrivers

Public Class Form1

    Public PLC As ModbusTCPCom = New ModbusTCPCom()

    Private SubID, SubID2, SubID3 As Integer
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        PLC.IPAddress = "192.168.1.10"
        PLC.PollRateOverride = "0"
        '
        SubID = PLC.Subscribe("30001", 1, 0, AddressOf DataReturned) '
        SubID2 = PLC.Subscribe("40001", 1, 0, AddressOf DataReturned)
        'SubID3 = PLC.Subscribe("B3:1", 2, 0, AddressOf DataReturned)
   End Sub
 Private Sub DataReturned(ByVal sender As Object, ByVal e As MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs)
        If e.PlcAddress = "30001" Then
            Label1.Text = e.Values(0)
        End If
        If e.PlcAddress = "40001" Then
            Label2.Text = e.Values(0)
        End If
     

    End Sub

Note:
Modbus TCP devices use client/server model. Client established a connection to server, then request info from server.
Modbus RTU devices use master/slave model. A Slave resides on a serial network (e.g. RS485) and listens for requests from a Modbus Master.

53
Feature Request / What ....no EZPLC?
« on: May 24, 2018, 12:51:10 PM »
I did a search for EZPLC  from EZ Automation and nothing came up. I ran into a few of these PLCs, have not had time to muck into.
Very low cost  and seemed to be very durable as well.

But just in case , Archie want to add it into his arsenal of drivers.

54
In my form load, I have the followings:
Code: [Select]
         InitializeCombo()
        'Dim dt As Date = PLC.ReadClock
        Application.DoEvents()
        System.Threading.Thread.Sleep(200)

        If PLCIsConnected Then
            PLC.Write("FromPC_Reset", 1)      'From PC Reset
            Sleep(250)
            PLC.Write("FromPC_Reset", 0)
        Else
            MessageBox.Show("PLC IS DISCONNECTED", "PLC WARNING", MessageBoxButtons.OK, MessageBoxIcon.Hand)
        End If

This same code works with  EthernetIPforSLCMicroCom1, but not with EthernetIPforCLXCom1.  I even tried a ReadClock, my variable got the clock time, and yet it always display PLC is disconnected msg.
Code: [Select]
Private Sub PLC_ConnectionEstablished(sender As Object, e As EventArgs) Handles PLC.ConnectionEstablished
        PLCIsConnected = True

    End Sub
TIA

55
Open Discussion / Checking whether a drive is mapped or substituted
« on: March 21, 2018, 01:55:59 PM »
To check if mapped drive exist then delete/disconnect it:
Code: [Select]
if exist X: (net use /d /y X:)

similarly, for substituted drive:
Code: [Select]
if exist X: (subst /d X:)
however, you can't delete/disc a mapped drive using subst or vise versa, hence there is a need to check whether a drive was mapped or substituted, using:
Code: [Select]
net use | find " V: " >nul && (net use /d /y V:) || (subst /d V:) >nul

56
Open Discussion / AAHMI and Norton virus scanner
« on: March 03, 2018, 04:17:43 PM »
AAHMI is now honorably detected by Norton virus scanner.
Hmm, that's strange! not sure what secrets Archie are keeping behind these DLLs.




Just kidding! I am sure it's false detection. can't wait for April's fool.

57
Support Questions / Can AAHMI talk to Siemen S7-200 PLC
« on: July 28, 2017, 09:25:12 AM »
Siemens S7-200 is a small PLC similar to AB Micrologix line,  use PPI protocol.
Their latest release Microwin v4 SP9 can be installed on win7- 64 bit.  The PC Access v1 SP6 which is an OPC server can support win 7 64 bit as well.

My question here is if AAHMI can talk to S7-200 directly without using OPC? 

58
Open Discussion / Check If File Exist
« on: July 25, 2017, 09:29:49 PM »
In certain machine, when cycle is complete, a result data file is generated.
The file is later processed and inserted into a production database.
Assuming the file is generated in the 'Result' folder, we move it to another folder 'XferedData' for processing.

One might ask, why dont we watch for files directly in the 'Result' folder? The reason for that is if we have to shutdown our application and the machine continue to generates files, those files will be ignored when the application is resumed.

Using a timer, we check if file exist in 'Result', if so move to 'XferedData' folder. A FileSystemWatcher will watch for file creation in 'XferedData' and process it accordingly. http://advancedhmi.com/forum/index.php?topic=1798.msg9980#msg9980

Since using a timer is not really my favorite, I would prefer to have an event driven, but not sure how to. TIA.

Code: [Select]
Private Sub CheckIfFilesExist()
        Try
            Dim sourceDir As String = "E:\Temp2\Result"
            'Check if file(s) exist , if so move to dest. dir for processing
            Dim files As String() = Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories)

            If (files.Length > 0) Then
                For Each Fil As String In files
                    Dim destFile As String = String.Format("{0}\{1}", destDir, Path.GetFileName(Fil))
                    System.IO.File.Move(Fil, destFile)
                Next
            End If
        Catch ex As Exception
            Debug.Print(ex.Message)
        End Try

    End Sub

59
Open Discussion / Parsing semi-structure text file
« on: June 17, 2017, 05:02:24 PM »
I have a result text file, it's sort of semi-structured text file. To simplify the problem, I will focus to TestPoints only. Within the file, there are many TestPoints Tp[x ] , but I am only interested in the first 10. And within a TestPoint , there are many items like Speed, RailPressure, ZeroPointPressure,.... again to simplify, I am only interested in Speed and ZeroPointPressure.
so for Tp[1], Speed = "0.100000"   and ZeroPointPressure =  "0.200000".

I would love to see it display in a gridview or so
Tp   Speed   ZeroPointPressure
1   "0.100000"   "0.200000"
2   "0.300000"   "0.400000"

and eventually  send to a SQL as one record ("0.100000","0.20000","0.300000","0.400000",...)

Thanks in advance.



--------------------------------------------------------------------------------
...
...

  Tp[1] #Index
    StructName = "ResultDataTPStruct"
    PositionType
      VarType = REG_DWORD 0x3
      Data = "4"
    NioRepeating
      VarType = REG_DWORD 0x3
      Data = "0"
    Variante
      VarType = REG_DWORD 0x3
      Data = "0"
    Speed
      StructName = "TdResultReal"
      Value
        VarType = REG_DWORD 0x4
        Data = "0.100000"
      Result
        VarType = REG_DWORD 0x3
        Data = "1"
      LoLim
        VarType = REG_DWORD 0x4
        Data = "-2.000000"
      UpLim
        VarType = REG_DWORD 0x4
        Data = "2.000000"
      CheckType
        VarType = REG_DWORD 0x3
        Data = "4"
    Railpressure
      StructName = "TdResultReal"
      Value
        VarType = REG_DWORD 0x4
        Data = "18.000000"
      Result
        VarType = REG_DWORD 0x3
        Data = "1"
      LoLim
        VarType = REG_DWORD 0x4
        Data = "-20.000000"
      UpLim
        VarType = REG_DWORD 0x4
        Data = "20.000000"
      CheckType
        VarType = REG_DWORD 0x3
        Data = "4"
    ZeroPointPressure
      StructName = "TdResultReal"
      Value
        VarType = REG_DWORD 0x4
        Data = "0.200000"
      Result
        VarType = REG_DWORD 0x3
        Data = "0"
....
...
  Tp[2] #Index
    StructName = "ResultDataTPStruct"
    PositionType
      VarType = REG_DWORD 0x3
      Data = "1"
    NioRepeating
      VarType = REG_DWORD 0x3
      Data = "0"
    Variante
      VarType = REG_DWORD 0x3
      Data = "0"
    Speed
      StructName = "TdResultReal"
...
-----------------------------------------------------------------------------------------

60
Open Discussion / FileSystemWatcher & checking for FileUploadComplete
« on: June 09, 2017, 12:07:26 PM »
Using FileSystemWatcher, one can monitor a folder for file creation, next making sure file upload complete before processing the file.
Code: [Select]
Public Function FileUploadCompleted(filename As String) As Boolean
        ' If the file can be opened for exclusive access it means that the file
        ' is no longer locked by another process.
        Try
            Using inputStream As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None)
                Return True
            End Using

        Catch generatedExceptionName As IOException
            Return False
        End Try
End Function

using a While loop, one can check for File Upload complete, but sleep time is not an efficient way, would you have a more efficient way to do this:
Code: [Select]
While Not FileUploadCompleted(e.FullPath)
            System.Threading.Thread.Sleep(500)
End While

Pages: 1 2 3 [4] 5 6