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

Pages: [1]
1
Support Questions / DataSubscriber2 Array Value issues
« on: July 07, 2023, 11:41:20 AM »
I noticed today that in the DataSubscriber2 object, when returning an Array of "Word" from a Micro800 series plc I get some really weird behaviors depending on the configuration.

In the first sceanario, I created individual entries in the DS2 control for each member of the Array, but interestingly enough, only the first instance of "Data_To_DC_PLC.Analog_Input[0]" fires within my ElseIf structure...

Code: [Select]
If e.Values IsNot Nothing And e.ErrorId = 0 Then
                SSB.Connected = True    'Set the Property to show connected.
                If e.PlcAddress = "Data_To_DC_PLC.DigitalInputs" Then
                    UpdateInputs(e.Values(0))
                ElseIf e.PlcAddress = "Data_From_DC_PLC[0]" Then
                    UpdateOutputs(e.Values(0))
                ElseIf e.PlcAddress = "Data_To_DC_PLC.Analog_Input[0]" Then
                    UpdateAnalog(0, e.Values(0))
                ElseIf e.PlcAddress = "Data_To_DC_PLC.Analog_Input[1]" Then
                    UpdateAnalog(1, e.Values(0))
                ElseIf e.PlcAddress = "Data_To_DC_PLC.Analog_Input[2]" Then
                    UpdateAnalog(2, e.Values(0))
                ElseIf e.PlcAddress = "Data_To_DC_PLC.Analog_Input[3]" Then
                    UpdateAnalog(3, e.Values(0))
                End If
            End If

So yeah strangely enough when I put breakpoints on the remaining ElseIf cases, they never fire.

When I set the Address to "Data_To_DC_PLC.Analog_Input" and then the NumberOfElements to 4, that's when it gets really strange. The ElseIf without the Array pointer 0 does fire, but the values returned have a count of 4 and only the first index actually has a value. The remaining 3 all say "Nothing"... (See attached). 

I have implemented a fix for this in my own code, but i don't quite understand why this is. The Raw Values actually have 2 bytes worth of data for each Tag and using that I am able to convert them into Int16 which gets me my values. But clearly something is broken and it isn't evaluating the raw data for subsequent members of an array properly.

Code: [Select]
If e.Values IsNot Nothing And e.ErrorId = 0 Then
                SSB.Connected = True    'Set the Property to show connected.
                If e.PlcAddress = "Data_To_DC_PLC.DigitalInputs" Then
                    UpdateInputs(e.Values(0))
                ElseIf e.PlcAddress = "Data_From_DC_PLC[0]" Then
                    UpdateOutputs(e.Values(0))
                ElseIf e.PlcAddress = "Data_To_DC_PLC.Analog_Input" Then
                    Dim i As Integer = BitConverter.ToInt16(e.RawData, 6)
                    UpdateAnalog(0, i)
                    i = BitConverter.ToInt16(e.RawData, 8)
                    UpdateAnalog(1, i)
                    i = BitConverter.ToInt16(e.RawData, 10)
                    UpdateAnalog(2, i)
                    i = BitConverter.ToInt16(e.RawData, 12)
                    UpdateAnalog(3, i)
                End If
            End If


2
Open Discussion / Tag Descriptions
« on: September 09, 2022, 09:39:33 AM »
This is a strange one... but I have been finding soo much good uses for this fantastic tool that I have a new request I wasn't sure if it could be done. Are you able to utlize the Ethernet/IP Driver for CLX to write Tag Descriptions? Not just the tag values.  Like the comment to the tag as well?

3
Support Questions / Back to back Writes
« on: December 17, 2021, 12:52:36 PM »
Hey, i have developed a custom app which uses a lot of direct .Write calls to the COM object, which in this case is a CLX driver.  So when I do the .write is there any reason I can't just go back to back with them? Do I have to put a thread sleep in there? Is the .Write function ASync or Sync? Can I get some result verifying that the write was successful?

Here's my code for example where the HMI is controlling the process of the machine through writing of values. It's necessary this way unfortunately based on the machine design.


Code: [Select]
Public Sub RunUserProgram()
        While Globals.CycleStart
            Dim cmdComplete As Boolean = False
            For i = 0 To MainMDIParent.childFormProgramEditor.MarkingOrder.Controls.Count - 1                           'Ensures they're executed in the right order
                For Each c As Control In MainMDIParent.childFormProgramEditor.MarkingOrder.Controls()                   'Loop through every entity
                    Dim tempControl As EntityBaseClass = c
                    If tempControl.entityID = i And tempControl.EntityCheckState = CheckState.Checked Then

                        MainMDIParent.childFormProgramEditor.SetEntityBgColor(c, Color.LimeGreen)

                        If TypeOf c Is MoveEntity Then
ProcessMoveEntity:
                            Dim entity As MoveEntity = c

                            If entity.Axis = "X" Then
                                PLC.Write("cmdAxis", 1)
                            ElseIf entity.Axis = "Z" Then
                                PLC.Write("cmdAxis", 2)
                            ElseIf entity.Axis = "A" Then
                                PLC.Write("cmdAxis", 3)
                            End If

                            If Globals.loggingMode = Globals.LoggingModeSelection.Debug Then MainMDIParent.childFormMain.UpdateMachineActivity("Sending target data: " & entity.TargetPos)
                            PLC.Write("cmdTarget", entity.TargetPos)            'Send the Target Position to the PLC
                            Thread.Sleep(100)

                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Verifying Command Position " & entity.Axis & ": " & entity.TargetPos)

                            'While Not verifyCmdPos(entity.TargetPos) And Not Globals.AbortActive
                            '    System.Threading.Thread.Sleep(100)
                            '    'targetOK = verifyCmdPos(entity.TargetPos)
                            'End While
RetryVerifyTarget:

                            If Not verifyCmdPos(entity.TargetPos) Then
                                Dim resultDlg As Integer = MessageBox.Show("Failed to verify Taget Position data", "Data Transmit Failure", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error)
                                If resultDlg = DialogResult.Retry Then
                                    GoTo RetryVerifyTarget
                                Else
                                    GoTo CancelOperation
                                End If
                            End If

                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Moving " & entity.Axis & " to: " & entity.TargetPos)

                            PLC.Write("cmdMoveCommand", 1)            'Write the command down to the PLC to move
                            Thread.Sleep(100)
                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Waiting for Move Done")

                            While Not verifyMoveDone(entity)  'Loop to check that the move is complete and axis is in position
                                If Globals.AbortActive Then GoTo CancelOperation
                                Thread.Sleep(100)
                            End While

                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Target Move Completed")
                        ElseIf TypeOf c Is TriggerBurnEntity Then
                            Dim entiy As TriggerBurnEntity = c
                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Triggering Laser")
                            PLC.Write("cmdLaserTrigger", 1)
                            Thread.Sleep(100)
                        ElseIf TypeOf c Is LoadProgramEntity Then
                            Dim entity As LoadProgramEntity = c
                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Changing Laser Program to: " & entity.ProgramNumber)
                            PLC.Write("cmdProgramNumber", entity.ProgramNumber)
                            Thread.Sleep(100)
                            PLC.Write("cmdPrgChg", 1)
                            Thread.Sleep(100)
                        ElseIf TypeOf c Is LotNumberEntity Then
                            Dim entity As LotNumberEntity = c
                            Call MainMDIParent.childFormMain.UpdateMachineActivity("Updating Lot Number: " & MainMDIParent.childFormMain.tbLotNumber.Text)
                            PLC.Write("cmdLotNumber", Globals.LotNumber)
                            Thread.Sleep(100)
                            PLC.Write("cmdBlockNumber", entity.BlockNumber)
                            Thread.Sleep(100)
                            PLC.Write("cmdProgramNumber", entity.ProgramNumber)
                            Thread.Sleep(100)
                            PLC.Write("cmdLotChange", 1)
                            Thread.Sleep(100)
                        ElseIf TypeOf c Is ChangeMarkingStateEntity Then
                            Dim entity As ChangeMarkingStateEntity = c
                            entity.parseBlockValues(entity.BlockNumbers, entity.StateCommand)
                            System.Threading.Thread.Sleep(100)
                            Exit Sub                                             'Skip the command complete from PLC since we arent using it.
                        End If
                    End If
                Next
            Next


CancelOperation:   'TODO Insert code to handle an error

        End While
    End Sub

4
Support Questions / AB Micro850 Program Scope tags
« on: December 07, 2021, 02:05:13 PM »
Does anyone know the syntax to access a tag which resides in the program scope of a Micro850 program?

I have a program called "Main" and I have created a tag under it's scope called "test" I just want to set that bool using a button. But what is the address for accessing the program scope tags?

"Program:Main.test"

is this it?

5
Support Questions / Variable for PLC IPAddress
« on: July 27, 2020, 10:59:07 AM »
I have clients that want to be able to change the PLC's IP Address and i was wondering if it were possible to write the ip to a string variable and have the COM object use that instead of manually entering it int he designer.  Any thoughts about a dynamic IP address? Maybe some routine that executes on startup?

6
Application Showcase / Controlling an entire machine as HMI and PLC.
« on: March 02, 2020, 11:58:04 AM »
This is an overview of a project I did later 2019 which showcases the potential power of AdvancedHMI and how nearly limitless it can be due to the fact that it's a .NET application.

The machine is a stand-alone laser marking station with a camera, fume extractor, servo motor for automated door, safety circuit, indicators lights, input sensors and push buttons. And they're all being controlled by AdvancedHMI.

I started with the idea of, do I really need a PLC? The short answer is NO, but I do need something to convert my Discrete 24v I/O into an Ethernet packet of data I can both read and write with. So I did some hunting online and found several resources, but ultimately decided to go with a product by Advantech called the ADAM-6052-D. It is a 16ch I/O 24vdc module which has Ethernet for both read and write capability.  They offer TCP/IP, ModbusTCP and many other protocols as the cheap cost of $235.00 at the time of this post. They also provide free .NET Libraries for their products which make integrating it a breeze! (THIS IS NOT A PLUG FOR THIS COMPANY OR PRODUCT. I AM NOT AFFILIATED) Just note there were several others I could have chosen but this one met all my criteria.

I bought this item and started testing it first in my lab and discovered it did exactly what I wanted, I could both read digital inputs and write digital outputs at my will. I had 2 other devices that I needed to communicate with and control a 2D Barcode Camera and Laser Marking System. This didn't take much effort as my company partners with Keyence this was a quick choice. Keyence allows for ASCII over TCP for controlling their system as well as reading status' any time.

So all the pieces were together and I started production on the machine.  Our customer has some very stringent requirements for the marking data and they would include a Checksum calculated on a marking data string which changes every part because it's serialized and the markings must be unique and cannot be duplicated. No problem. AdvancedHMI Framework being .NET, it' s a piece of cake to write up a Function to read the string from the Laser, manipulate the data, check it against a database with a SQL query for uniqueness and send it back down the Laser to be marked. Then with my custom "Auto Process" Thread which is constantly looping in the background similar to how a PLC does, I could trigger the actions of all the machinery via the Discrete I/O from the ADAM module and after marking, trigger the camera to read the marking over TCP and verify read versus the intending marking.

So all of this was done using the power of .NET and the AdvancedHMI framework was the perfect solution for me. The machine is running in production now with no issues and it has massive amount of tasks and is done with some super simple cost effective components. This was posted just as an encouragement to think outside of the box for this product. It has much more powerful potential than just a simple HMI application. Not that it doesn't do so very well, it does, but it's limitless with what it can do.

7
Feature Request / Driver communications log (error log)
« on: February 27, 2020, 10:48:48 AM »
It would be amazing if there was an ability to set a Log file for the communications driver. I would have saved so much time if I could go back and look at the driver to see what error's occurred when testing something.  Could it be possible to enable a Log feature into the driver and have it store to a .txt file locally?

8
Support Questions / ModbusTCP parsing a PLC Boolean Array
« on: May 29, 2018, 10:10:26 AM »
I have a job i'm doing for a customer that wants me to make an interface for their PLC.  The PLC is of type GE CPE330.  I'm using ModbusTCP to interface with it successfully so far.  I'm at a snag where I need to parse through a boolean array they have to determine what faults are active in the system.  It's 100 booleans and I need to send it over ModbusTCP to the HMI. I can use straight booleans or i can pack it into an INT somehow. 

But what on the AHMI side should I do to evaluate that data? I'm using a DataSubscriber 2 already on my MDI Parent for other items and I can add whatever element I need to that which will constantly check the machine for the active faults.  But what data type... how do I address it? How do I parse it?

I have 40500 and UP to work with for Modbus Addresses.

Please your thoughts are very much appreciated.

9
Support Questions / Suggestion for a change on ALL controls
« on: January 24, 2018, 07:28:10 AM »
I have had several times now where there's something causing one of the controls in my form to constantly keep adding more COMComponents to my form? Everytime I build or make a code change and come back to the Designer, it'll add another one!!  I have looked through each control on my form one by one using VS and each one is set for the same exact ComComponent but yet still it keeps adding them. I noticed in the logic of every control basically if you add it to the form and there is no ComComponent specified that it will add one automatically for you.  I think this is problematic.

Can you either:
A.) Figure out why and fix that
B.) Instead of adding them either do nothing or message box that you need to add one to the form and list the name of the control which is requesting one be added.

Thanks

10
Additional Components / NEW!!! User Management Plugin
« on: December 12, 2017, 12:23:55 PM »
Hey guys,

Per a request from a customer I created a new UserManagement component of my own.  There are plenty of tutorials out there on how to do this in VB.net but for those who aren't code savvy I thought I would share mine and offer any help I can to those who reply to this thread.

First off here is what it looks like on MY user interface.

ScreenShots:




Features:
  • Login/Logout function
  • Local .csv database of users and passwords
  • 3 Levels of privileges Operator, Supervisor, Administrator
  • Passwords are stored as Encrypted strings
  • Public events for Login Logout each page can subscribe to
Usage:
Start by adding the file(s) to your project. Right click on your project name and select "Add --> Existing Item"


Please make sure to select all of the files in the .zip which were including as an attachment in this post.


Login:
Next somewhere on your project add a Button control to your form and double-click on it to add the handler for the Click event and show the related code.
The is a function in the UserManagement Class called "Login" this function when called for the very first time ever on a computer will check if the local database file (.csv) exists yet on the computer.  If it does not then the function will create it and also add the "Admin" user to the database.  The "Admin" user has the default login of User: Admin   Pass: password.  Note that the Username is NOT case sensitive but the Password however is.

Add a call to this Login function using code similar to this.
Code: [Select]
    Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
        frmLogin.ShowDialog()
        If Not UserManagement.currentUser = "" Then
            'Do Something here to handle the login succesfull... maybe update a label.text control with the UserManagement.currentUser.
            'There will also be a UserManagement.currentPrivilage which will be set based on the credentials of the user which logged in.
        End If
    End Sub

When the function is called it will display the Login Dialog.  The Login Dialog will handle the call to the login function within the UserManagement.vb. When the login is successful the function will set 2 shared variables in the UserManagement class for the "currentUser" and "currentPrivilage".  It will also fire a Shared Event for the Login.

It is recommended that you have each form which will dynamically be changing based on the User logged in and their Privileges to subscribe to the public events of "userLoggedIn" and "userLoggedOut".  Here is how to handle those events.

In the Load event for the Form in question, add a handler for each event.
Code: [Select]
        AddHandler UserManagement.userLoggedIn, AddressOf handleUserLoggedIn
        AddHandler UserManagement.userLoggedOut, AddressOf handlerUserLoggedOut

Next create the Subs for each of those events or you can copy this code and add it to your own.
Code: [Select]
    Private Sub handleUserLoggedIn()
        If UserManagement.currentPrivilage = UserManagement.Privilage.Administrator Or UserManagement.currentPrivilage = UserManagement.Privilage.Supervisor Then
            Me.tbManualVinEntry.Enabled = True
        End If
    End Sub
    Private Sub handlerUserLoggedOut()
        If Not UserManagement.currentPrivilage = UserManagement.Privilage.Administrator Or Not UserManagement.currentPrivilage = UserManagement.Privilage.Supervisor Then
            Me.tbManualVinEntry.Enabled = False
        End If
    End Sub

In these examples I am checking the value of the privilege for the current user who is logged in. That is stored in the UserManagement.currentPrivilage variable. Depending on the privilege of the user you can create different methods to turn On or OFF various user controls on the form.  Each form can subscribe to these events and alter the controls within accordingly.

Logout:
Finally back on the main form where the Login button resides.  Add another button for the Logout functionality. Then in the Click event of the button add the following code.
Code: [Select]
        Dim myUserManagement As New UserManagement
        Call myUserManagement.Logout()

Adding a User:
To add a user, somewhere in you project create a button to add a user. Double click on this button to access the click event code.  Add the following code.
Code: [Select]
    Private Sub btnAddNewUser_Click(sender As Object, e As EventArgs) Handles btnAddNewUser.Click
        frmAddUser.ShowDialog()
    End Sub

This will open up the frmAddUser so you can properly add a user to the database.  NOTE: It is suggested that the visibility property of this button be set to False by default and only enabled if the current user logged in has a Privilege of Administrator.  That can be handled by reading the Login section above.


The addUser function will check if the username already exists in the database and if so will prompt if you would like to overwrite it. This gives you the ability to just change the password easily if needed.  After you click "Add User" the function will display a messagebox to inform you if it was a success or a failure.

Deleteing a User:
In my example there is a combo box which I populate on the load event of the form of all of the users in the database. To do this add a ComboBox


To do this, add a Combo Box control to your form, set the Name property to "cboUserList" then open up the Load Event logic of the form.  Add the following code (make sure you change the name of the Combo Box control to match your project if needed)
Code: [Select]
        Me.cboUserList.Items.Clear()
        Dim userList As New List(Of String)
        Dim _userManagement As New UserManagement
        _userManagement.getUserList(userList)

        If Not userList.Count = 0 Then
            For i = 0 To userList.Count - 1
                Me.cboUserList.Items.Add(userList.Item(i).ToString)
            Next
        End If

Next add a new button control to your form and set the Text property to "Remove User".  Double click on the button to open the click event code.  Add the following code to yours keeping in mind the name of the Combo Box from the previous step.
Code: [Select]
    Private Sub btnDeleteSelectedUser_Click(sender As Object, e As EventArgs) Handles btnDeleteSelectedUser.Click
        If Not Me.cboUserList.Text = Nothing Then
            Dim _userManagement As New UserManagement
            _userManagement.deleteExistingUser(Me.cboUserList.Text)
            Dim i As Integer = Me.cboUserList.SelectedIndex
            Me.cboUserList.Items.RemoveAt(i)
        End If
    End Sub

This function will find the Username in the database and remove it.  The comboBox will also remove the item from the list.

Please let me know if you have any questions below or of something isn't clear and I will modify this post and elaborate more.

Thanks! and enjoy.


11
Open Discussion / Wiki
« on: November 10, 2017, 07:19:51 AM »
Archie,

There's a lot missing on the Wiki which some users like Phrog and Myself would be happy to contribute to when we get time. But I can't seem to make an account and my login for this doesn't work.
Can you either A fix it so people can make an account or B add a thread where we can request to have you make an account for us.
Unless of course you don't want public contributions to the pages but then why would it be a Wiki :)

Thanks

12
Support Questions / Lost all my Comms
« on: November 03, 2017, 11:26:55 AM »
Ok so I'm doing this remote update and something I did to my project caused me to loose all my communication from the HMI to the PLC.  When I test an older .exe which i used this ones source code to start from it works... but my new one doesn't.  All of the controls say No Response From PLC.  I made one button larger and it tells me this (See attachment). What did I do wrong?  Can anyone help me figure it out please.   All the IP and Port and Timeout settings match and I tried to do a code comparison of all the files in the projects except the AdvancedHMI project and they all appear to be identical.

Micro850 PLC

13
Support Questions / DataSubscriber2 Number of Elements
« on: November 02, 2017, 02:55:15 PM »
So I have a machine which is across the country and I'm trying to do some upgrades to the HMI code so I don't have the machine to test it live and I want to get as much done as I can before going there.

That being said...  it's a Micro850 PLC from AB and I have a DataSubscriber2 component and I'd like to return a REAL array of 32 items.

So I add the Tag to the Members and then under the "Number of Elements" I say 32.
When this returns... how do I parse them individually?  Could you offer me some sample logic to parse a 32 element array vb.net?

14
Support Questions / Writing a large number of tag values at once
« on: September 12, 2017, 01:12:10 PM »
Doing an application where I need to send down a bunch of Real Numbers to a micro800 plc on a button_press event.

I noticed that there are two different types of Writes for the Com component.  There is plain .Write and then there is .BeginWrite.

I have 32 tags to write down, which in the plc is actually an array of 32 different real numbers. Ex:  PartCoordinatesX[1...32]
also PartCoordinatesY[1...32].

What is the best way to accomplish this? I can loop through until it's done but how do you get a synchronous feed back that the data was sent successfully? Is there any handshake like that? 

OR does the BeginWrite which has arguments of "startAddress, Number of Elements" seem like the better option.  In either case, whats the best course here?  And also is there some synchronous mode to write data into the plc which gives me feedback?

Thanks in advance!

15
Application Showcase / MDIParent Form Model
« on: September 11, 2017, 11:36:28 AM »
I've used AHMI on several HMI Applications already but I didn't like the way that change the pages worked so I made my own MDI-Parent/Child form control and I've adapted it to work quite smoothly.  Having used this on several machines already I can say that I'm pretty happy with it.

This particular application is servicing a Micro850 PLC from Allen-Bradley over Ethernet and which has 2 Servo Linear stages for positioning parts directly under a laser marker.  There is also a built in Keyence camera which is being controlled by this application over Winsock TCP/IP.  This app has the ability to build custom part configurations for differing setups as well as store and open previously saved ones.  The HMI will synchronize with the PLC the coordinates for each of the parts programmed.

It also logs machine activity and Part data including Serial Number and Camera Pass/Fail to an excel spreadsheet per the customers request.

I have disabled the PLC coms so when you download the sample make sure to re-enable them if you plan on using this. AdvancedHMIControls project and then in the Subscriptionhandler.vb un-comment the SubscribeToComDriver method.











https://drive.google.com/drive/folders/0B8Vb3TS6SQwxTEROWWR0X1RwcTg?usp=sharing

Just click on the drop down above the files list and there will be an option to download it.

Pages: [1]