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 - seth350

Pages: [1]
1
Support Questions / RaspberryPi Debugging CPU Usage
« on: June 20, 2018, 10:08:32 AM »
Good morning,

I have been battling high cpu usage for some time now. It seems the app starts out small and grows over time until it locks up. The app is running in Mono.

In the RaspberryPi, you can open a new terminal window and enter the command type in:
Code: [Select]
top
This displays the processes currently running and the system resources. A little trick while in this command is to press Shift + H, this will display all of the threads currently running and their resources.

I wanted to share some screenshots of what my app is doing to try to figure out if its something in MY code, Mono, or if it is something in AdvancedHMI causing this.

Archie,
Are the "Threadpool work" threads apart of AHMI?

Mono Version: 5.2.0.215
AdvancedHMI Version: 3.99x


2
Feature Request / OPC-UA Driver
« on: June 16, 2018, 10:24:24 PM »
I know that the OPC-DA SDK is finicky but I wanted to throw this out there for future consideration.

Now that we are in this calamity of IoT, more and more devices are turning on to OPC-UA. There are some open source projects out there and SDKs to add OPC-UA to a .NET project. I have not attempted to integrate it into AdvancedHMI yet. I haven’t had any downtime to give it a try.

If OPC-UA could be added to AdvancedHMI, that would mean that every single PLC in my plant could be connected to an AdvancedHMI app. As well as newer devices that are coming out.

The OPC-DA driver it has now doesn’t seem to work correctly with all servers. Or at least with a B&R plc.
This PLC can do ModbusTCP, explicit EIP, Powerlink, OPC-DA, and OPC-UA. As well as HTTP and TCP/UDP.

Just a suggestion...

3
Open Discussion / Event Arguments: Is this wrong?
« on: January 30, 2018, 04:11:54 PM »
Good afternoon all,

I have a question regarding event arguments and their correct use.

I have an app that I have created several different EventArgs for different events. Each passing the needed information to the event sub.

The class this sub is located in is declared once from the MainForm. In this sub, I am using StatusArgs as my event argument.
My question is, is it necessary for me to be calling "New StatusArgs" every time I raise an event? Would calling "New StatusArgs" be creating a new instance that eventually uses up resources?

I suppose the real question is, after calling "New StatusArgs" and setting the information in it, does the instance hang out forever in memory?

Would the better option be to create one instance of StatusArgs for the class, and then just set the arguments every time I raise the event? Would doing this essentially overwrite the variables that are stored in the instance?



Code: [Select]
    Public Sub VerifyPart(ByVal scan As String)

        Dim partFound As Boolean = False

        For Each item As ListViewItem In _list.Items
            If scan = item.SubItems.Item(1).Text Then
                If CheckOffItem(item) = True Then
                    RaiseEvent OnPartProcessed(Me, New StatusArgs(0, String.Format("Part# {0} is valid! Please scan the next part.", scan), Color.Green, Color.White))
                    _audio.ValidScan()
                Else
                    RaiseEvent OnPartProcessed(Me, New StatusArgs(2, String.Format("Part# {0} previously scanned!" & vbNewLine & "Verify your quanity and try again.", scan), Color.Red, Color.White))
                    _audio.InvalidScan()
                End If
                partFound = True
            End If
        Next item

        If partFound = False Then
            If scan = "NoRead" Then
                RaiseEvent OnPartProcessed(Me, New StatusArgs(2, "Scanner did not find a bar code. Try again.", Color.Red, Color.White))
                RaiseEvent InvalidLog(Me, New StatusArgs(scan, "Scanner did not find a bar code. No Read."))
            Else
                RaiseEvent OnPartProcessed(Me, New StatusArgs(2, String.Format("Part# {0} is invalid. Please verify your parts.", scan), Color.Red, Color.White))
                RaiseEvent InvalidLog(Me, New StatusArgs(scan, String.Format("Part# {0} was not found in the current parts list.", scan)))
                _audio.InvalidScan()
            End If

        End If

    End Sub

Code: [Select]
''' <summary>
''' Station Status Arguments Class For Passing Information To The Status Panel.
''' </summary>
Public Class StatusArgs
    Inherits EventArgs

    Private _code As Integer
    Private _msg As String
    Private _scan As String
    Private _backclr As Color
    Private _foreclr As Color

    ''' <summary>
    ''' Creates a new instance to pass status arguments to the status panel.
    ''' </summary>
    ''' <param name="code">Determines what the graphic and color is set to. 0=No Change To Image 1=Scanning Complete 2=Scan Invalid 3=General Alarm 4=Ready</param>
    ''' <param name="msg">Text to set the status to.</param>
    ''' <param name="backclr">Specify what color to set backcolor on status panel.</param>
    ''' <param name="foreclr">Specify what color to set the text to.</param>
    Public Sub New(ByVal code As Integer, ByVal msg As String, ByVal backclr As Color, ByVal foreclr As Color)

        _code = code
        _msg = msg
        _backclr = backclr
        _foreclr = foreclr

    End Sub

    ''' <summary>
    ''' Creates new instance of StatusArgs to pass scanned code and message.
    ''' </summary>
    ''' <param name="scan">The scanned bar code to pass.</param>
    ''' <param name="msg">The message to attach.</param>
    Public Sub New(ByVal scan As String, ByVal msg As String)
        _scan = scan
        _msg = msg
    End Sub

    ''' <summary>
    ''' Indicates what status image/color should be displayed.
    ''' </summary>
    ''' <returns>Integer</returns>
    Public ReadOnly Property Code As Integer
        Get
            Return _code
        End Get
    End Property

    ''' <summary>
    ''' Gets the status message.
    ''' </summary>
    ''' <returns>String</returns>
    Public ReadOnly Property Message As String
        Get
            Return _msg
        End Get
    End Property

    ''' <summary>
    ''' Gets the scanned code associated with this event.
    ''' </summary>
    ''' <returns>String</returns>
    Public ReadOnly Property Scan As String
        Get
            Return _scan
        End Get
    End Property

    ''' <summary>
    ''' Gets the image that the status image should be set to.
    ''' </summary>
    ''' <returns>Image</returns>
    Public ReadOnly Property Image As Image
        Get
            Select Case _code
                Case 0
                    Return Nothing
                Case 1 'scanning complete
                    Return My.Resources.greenCheck
                Case 2 'invalid scan
                    Return My.Resources.traffic_light_red
                Case 3
                    Return My.Resources.important
                Case 4 'station ready
                    Return My.Resources.traffic_light_green
                Case Else
                    Return My.Resources.gear
            End Select
        End Get
    End Property

    ''' <summary>
    ''' Gets the back color of the status image and message.
    ''' </summary>
    ''' <returns>Color</returns>
    Public ReadOnly Property BackColor As Color
        Get
            Return _backclr
        End Get
    End Property

    ''' <summary>
    ''' Gets the fore ground color for the status message.
    ''' </summary>
    ''' <returns>Color</returns>
    Public ReadOnly Property ForeColor As Color
        Get
            Return _foreclr
        End Get
    End Property

End Class

 


4
Application Showcase / Bar Code Verification App
« on: January 07, 2018, 11:38:11 PM »
I don’t usually post my work but I would like to hear others thoughts. Feedback welcome.

My company wanted a system to verify that we are using  the correct components during assembly.
I managed to do this using the following:

AdvancedHMI running on RaspberryPi3 with Mono
Compactlogix PLC
Cognex 8050 WiFi scanner
Prosoft WiFi Radio (serves as hotspot for the raspberries)
SQL Server 2014

I tried to make this app as portable as possible. All stations are running the same exact app with an ini file for its settings. Running three stations at the moment. Each station is configurable using bits from the PLC to bypass or enable scanning of certain components at each station. We needed the ability to change where certain components get scanned during assembly. In the case of an absence or special case scenario.

The PLC is also used to connect to the scanners and relays the scanned data from the respective scanner to that scanners respective station. The SQL lookups are done in AHMI. I initially tried to use Factorytalk Transaction Manager, but AHMI was faster in getting the SQL data.

The jist of operation works as follows:
An operator must first scan a SKU or UPC Number to see what they should be scanning. AHMI receives the scanned code from the PLC and then determines if they scanned a SKU or a UPC. If valid, AHMI then requests the BOM from SQL using WHERE SKU/UPC=‘scan’. If data is received, AHMI creates a new data table and stuffs the received BOM into it. It will then send the BOM to a Station UDT in the PLC for retaining the data. AHMI will then check which components are enabled to be scanned and then build the listview with just those parts.
The operator can then start scanning their components to verify they are correct for the SKU/UPC being assembled.
As the operator scans each component, AHMI will verify the scan matches one in the listview and check off and highlight the row that was scanned. It will also determine if a component has already been scanned. The status area gives the operator information as to what effect their last scan had.
Once all components are scanned, AHMI will alert the operator and then clear all data from the listview and labels.

Wish list:
Ability to use more than one scanner per station. (Haven’t figured this out yet)
Use something other than Linux to run AHMI. Porting to Mono is full of gotchas.
Station performance metrics



5
Support Questions / Problem connecting to PLC5/30 DHRIO
« on: October 13, 2017, 10:04:23 AM »
Ive got a ENBT-DHRIO in a contrologix rack that is giving us access to a DH+ network over ethernet.
Theres a SLC and two PLC5/30s on the DH+.

Using the PLC5toDHRIO driver, I am only able to connect to one of the PLC5s and not the other. One is at Node 4 and the other at Node 50.
I am able to go online with both PLC5s over ethernet as well. RsLinx is seeing both of them and can also monitor tags from Linx.

I have looked at the channel config of both PLC5s and the only difference is the baud rate on channel 0.

Driver settings:

CIP Connection Size: 258
DHRIO Slot: 0
PollRate: 500
Port: 44818
RoutePath:
Timeout: 5000

DHRIO Channel: A
Disable Subscriptions: False
IniFileName:
IniFileSection:
Max PCCC Packet Size: 236
Target DHPlus Node: 50

It does generate an exception on startup "Read Failed - 2. Unknown Message - 2"

Wireshark shows the handshake between my pc and the ENBT adapter. Then they begin transmitting "Implicit Data - Class (0xa6)" No visible errors. The wireshark for the working PLC5 doesnt appear any different.

Any ideas?

6
Open Discussion / Where do we draw the line?
« on: July 20, 2017, 11:21:21 PM »
Hey there,
So I have been developing a bar code/bom lookup using advanced hmi and some cognex bar code scanners. This project started out using a PLC, with aHMI being just just an HMI. Database transactions were being made through Factorytalk Transaction Manager.
That was a month or two ago...
Today, the PLC is no longer in the picture and neither is Transaction Manager. Everything is done in aHMI. Which made me wonder...where is the line drawn between controling a machine/process/whatever with aHMI or with a PLC?

Both can do much of the same, if not more than the other or easier than the other.

Where do you draw the line?



7
Open Discussion / Custom Component Debugging
« on: June 27, 2017, 03:11:32 PM »
I have been working on creating a component for a Cognex Dataman BCR using the Dataman SDK.
Initial tests proved that I could add the component, set the IP address in the properties and once the application was started I could start receiving the scanned bar codes in AdvancedHMI.

My question is, I need to add another scanner component to the application. How would I go about debugging the two components separately? I am able to debug the component code during runtime, but it seems it is only showing me the running code for the last declared component. If that makes sense?

*Edit*
Or should the component (in my case), add a .vb file to the Solution Explorer for Scanner1 and Scanner2, respectively?
Since each scanner is it's own entity, it can't necessarily be running from one .vb file? Or can it?

I.E.,
In MainForm.Designer.vb
Code: [Select]
Friend WithEvents Scanner1 As CognexDatamanControl.CognexDataman
Friend WithEvents Scanner2 As CognexDatamanControl.CognexDataman ' Last declared component

Also, shouldn't these be initialized as:
Code: [Select]
Friend WithEvents Scanner1 As New CognexDatamanControl.CognexDataman
Friend WithEvents Scanner2 As New CognexDatamanControl.CognexDataman

Perhaps I do not fully understand how the component is built behind the scenes?

8
Open Discussion / Barcoded Assembly Verification
« on: May 17, 2017, 10:02:51 AM »
Morning folks,

We are getting into tracability of parts and such at our facility and was wondering if anyone else has the same or has implemented a system for that?

What database did you use for part lookup? Any PC software involved? Interfaces to database?

9
Support Questions / CLX EIP Driver No Response From PLC
« on: May 09, 2017, 09:55:12 AM »
Trying to read an array of 27 strings that are all standard length. It seems the driver gets hung up on reading anything over 20, so I divided the reads. Sometimes this works and sometimes it doesn't.

I also tried creating another driver to handle one half, and that gave the same results.

Driver is set to 1000 poll rate with 8000 timeout.

Any ideas?

Code: [Select]
Public Class MainForm
    '*******************************************************************************
    '* Stop polling when the form is not visible in order to reduce communications
    '* Copy this section of code to every new form created
    '*******************************************************************************
    Private NotFirstShow As Boolean

    Private Sub Form_VisibleChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.VisibleChanged
        '* Do not start comms on first show in case it was set to disable in design mode
        If NotFirstShow Then
            AdvancedHMIDrivers.Utilities.StopComsOnHidden(components, Me)
        Else
            NotFirstShow = True
        End If
    End Sub

    '***************************************************************
    '* .NET does not close hidden forms, so do it here
    '* to make sure forms are disposed and drivers close
    '***************************************************************
    Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Dim index As Integer
        While index < My.Application.OpenForms.Count
            If My.Application.OpenForms(index) IsNot Me Then
                My.Application.OpenForms(index).Close()
            End If
            index += 1
        End While
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim stuff() As String
        Dim junk() As String
        Dim ack As Boolean
        Dim upc As String


        stuff = conPLC1.Read("PROGRAM:MainProgram.Station1.SQL.Receive.Component[0]", 13)
        junk = conPLC1.Read("PROGRAM:MainProgram.Station1.SQL.Receive.Component[13]", 14)

        complist.Items.Clear()
        complist.Items.AddRange(stuff)
        complist.Items.AddRange(junk)


        conPLC1.Write("PROGRAM:MainProgram.Station1.resultNewArrivalACK", 1)
        ack = conPLC1.Read("PROGRAM:MainProgram.Station1.resultNewArrivalACK")

        If ack = True Then

            conPLC1.Write("PROGRAM:MainProgram.Station1.resultNewArrivalACK", 0)

        End If



        upc = upclabel.Text.ToString

        If upc.Contains("08856") Then

            If upc.Length = 13 Then

                checklabel.Text = "Scanned Code Is A UPC Number. Transferred To FTTM."

            Else

                checklabel.Text = "Scanned Code Is Not A UPC Number. Copied To Compare Array In PLC."

            End If

        End If
    End Sub
End Class

10
Support Questions / Logging to database VB Question
« on: March 24, 2017, 12:16:54 PM »
Hello folks,

Been cutting my teeth with VB and I am just about down to my gums lol

I have a seemingly simple app using AHMI to connect to a CLGX plc and log a variable to an Access db. Once I have this working, I will expand to more variables.
 
Anyways, I have probably coded down a rabbit hole...
My problem is that it seems the code is not opening the connection to the database, or maybe I don't need to handle the connection in the way I am doing it?

Previously when I tried to run a different set of code, it would connect, log only a few variables, and then I would get an exception stating that the connection to the db was already open. I figured, "Ok, Someway or another the code to open the connection is being ran more than once, so I need to control when to open the connection based on the state of the connection."

And this is what I ended up with... 


Code: [Select]
Public Sub DataSubscriber21_DataChanged(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles DataSubscriber21.DataChanged

        Dim phvalue As Single

        If e.PlcAddress = "Process.Waste_Water_Facility.City.Pit.Ph.Reading" Then
            phvalue = e.Values(0)
            testdisp1.Value = phvalue

        End If

        If phvalue > 0 Then 'Log only if value is healthy.

            Dim sqlcmd As String
            Dim objCmd As New OleDb.OleDbCommand
            Dim conn = New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Documents\phdata.accdb")
            Dim connstate As Int16
            Dim dblogstate As Int16 = 1


            If ConnectionState.Closed Then 'Set connstate to 1 if DB Connection is Closed
                connstate = 1

            ElseIf ConnectionState.Connecting Then 'Set connstate to 2 if DB Connection is Connecting
                connstate = 2

            ElseIf ConnectionState.Open Then 'Set connstate to 3 if DB Connection is Connected
                connstate = 3

            End If

            Select Case dblogstate
                Case 1 'Open connection if one does not exist.

                    If connstate = 3 Then
                        dblogstate = 3 'Already connected to db, start logging.

                    ElseIf connstate = 1 Then
                        dblogstate = 2

                    End If

                    dbstatlabel.ForeColor = Color.Gray
                    dbstatlabel.Text = "Not Connected To Database"

                Case 2 'Connect to database

                    Try
                        conn.Open()
                        dbstatlabel.ForeColor = Color.Blue
                        dbstatlabel.Text = "Connecting to Database..."

                    Catch ex As Exce
                        MsgBox(ex.Message)
                        dbstatlabel.ForeColor = Color.Red
                        dbstatlabel.Text = "Database Error!"

                    End Try

                    If connstate = 3 Then 'Connected to database, start logging.
                        dblogstate = 3

                    ElseIf connstate = 2 Then 'Trying to connect to database.
                        dblogstate = 2 'Keep trying to connect.
                        dbstatlabel.ForeColor = Color.Blue
                        dbstatlabel.Text = "Trying to connect to Database..."

                    End If

                Case 3 'Connected to database
                    dbstatlabel.ForeColor = Color.Green
                    dbstatlabel.Text = "Connected to Database"

                    Try
                        sqlcmd = "INSERT INTO CitypH (Cityph) VALUES ('" & phvalue & "')"
                        objCmd = New OleDb.OleDbCommand(sqlcmd, conn) 'Set the command
                        objCmd.ExecuteNonQuery() 'Execute the SQL command

                    Catch ex As Exception
                        MsgBox(ex.Message)
                        dbstatlabel.ForeColor = Color.Red
                        dbstatlabel.Text = "Database Error!"

                    End Try

                Case Else
                    dbstatlabel.ForeColor = Color.Red
                    dbstatlabel.Text = "Program Error!"

            End Select
        End If

    End Sub

11
Open Discussion / SCADA Network Question
« on: October 30, 2016, 09:27:51 PM »
Hello everyone,
First I would like to say thank you Archie for a wonderful HMI!

I am going to be using AdvHMI for our new and first SCADA system.
I myself have never done one but from what I have seen, it is a plant HMI. All plant information in one place so to speak.
My question is how do other people typically setup their plant network? For example, we have a mixed network of two subnets. One is corporate controlled and is the DHCP server for all associate computers. The corporate range is 10.40.X.X. The other is a local network of which all the machines are connected. It's range is 192.168.16.X. There are around 30 machines, each with multiple Ethernet/ip devices. These two networks are connected somewhere that allows traffic to/from either network. Would it be wise to setup another subnet for communication to the SCADA PC? My worry is data collisions using the machine network. How have you guys done it?


Pages: [1]