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

Pages: [1] 2 3 4
1
Additional Components / CLX Tag Browser AHMI Controls
« on: January 20, 2021, 10:11:14 PM »
Related to this topic:

   https://www.advancedhmi.com/forum/index.php?topic=2835.0

Attached are 2 possible AHMI controls that could be used for getting and browsing CLX tags.
They do require 3.99y Beta38 or later version of AHMI.

They are both set to observe the initial state and subsequent changes of the driver's DisableSubscriptions property.
Tags will be re-populated whenever this property changes from True to False.
This could possibly work to show tags from different devices with the change of the driver's IP address.

The TreeView based control is also set to sort the tags.

These controls could possibly be further modified.

2
Additional Components / Other Modbus Testers
« on: December 12, 2020, 04:11:38 AM »
One more handy Modbus tool:

   https://github.com/ClassicDIY/ModbusTool

--------------------------------------------------------------

Here is also a link to another free Modbus testing program:

   https://www.se.com/us/en/faqs/FA180037/

And to quote the author of the page where I found it:
"Modbus Tester from Schneider Electric is a free proprietary Windows GUI program for reading Modbus registers. It supports Modbus RTU and TCP."

   http://www.dalescott.net/modbus-development/

It looks like a handy quick testing tool but for registers only.

3
Tips & Tricks / Reading the CIP Identity of any Ethernet/IP device
« on: November 30, 2020, 10:36:26 PM »
This is just an example code - hopefully accurate, combination of these wiki topics:

   https://advancedhmi.com/documentation/index.php?title=Reading_the_CIP_Identity_of_any_Ethernet/IP_device
   https://advancedhmi.com/documentation/index.php?title=Generic_Ethernet/IP_and_CIP_Technical_Information
   https://advancedhmi.com/documentation/index.php?title=Class_Codes_for_ControlLogix

See the attached picture of the MainForm which is reflective of the code.

Everything can be further simplified by:

   - removing all the buttons and moving their action codes to the MainForm's Load event
   - using only 1 textbox and appending the received values to the text

Code: [Select]
    Private AttributeReadDeviceProductCode As UInteger
    Private AttributeReadDeviceProcessorStatus As UInteger
    Private AttributeReadDeviceName As UInteger
    Private AttributeReadDeviceSerialNumber As UInteger

    Private Sub ButtonProcessorStatus_Click(sender As Object, e As EventArgs) Handles btnProcessorStatus.Click
        AttributeReadDeviceProcessorStatus = EthernetIPforCLXCom1.BeginGetAttributeSingle(1, 1, 5)
    End Sub

    Private Sub ButtonProductCode_Click(sender As Object, e As EventArgs) Handles btnProductCode.Click
        AttributeReadDeviceProductCode = EthernetIPforCLXCom1.BeginGetAttributeSingle(1, 1, 3)
    End Sub

    Private Sub ButtonDeviceName_Click(sender As Object, e As EventArgs) Handles btnDeviceName.Click
        AttributeReadDeviceName = EthernetIPforCLXCom1.BeginGetAttributeSingle(1, 1, 7)
    End Sub

    Private Sub ButtonSerialNumber_Click(sender As Object, e As EventArgs) Handles btnSerialNumber.Click
        AttributeReadDeviceSerialNumber = EthernetIPforCLXCom1.BeginGetAttributeSingle(1, 1, 6)
    End Sub

    Private Sub EthernetIPforCLXCom1_DataReceived(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles EthernetIPforCLXCom1.DataReceived
        If e.ErrorId = 0 AndAlso e.Values IsNot Nothing AndAlso e.Values.Count > 0 Then
            If e.TransactionNumber = AttributeReadDeviceProcessorStatus Then
                Dim bitString As String = Convert.ToString(CInt(e.Values(0)), 2).PadLeft(16, "0"c)
                Dim status As UInteger

                For i = 4 To 7
                    If bitString(15 - i) = "1" Then
                        status += 2 ^ (i - 4)
                    End If
                Next

                Select Case status
                    Case 0
                        TextBoxStatus.Text = "Self-Testing or Unknown"
                    Case 1
                        TextBoxStatus.Text = "Firmware Update in Progress"
                    Case 2
                        TextBoxStatus.Text = "Reserved"
                    Case 3
                        TextBoxStatus.Text = "Reserved"
                    Case 4
                        TextBoxStatus.Text = "Non-Volatile Configuration Bad"
                    Case 5
                        TextBoxStatus.Text = "Major Fault - either bit 10 or bit 11 is true (1)"
                    Case 6
                        TextBoxStatus.Text = "Programmable logic executing (Run)"
                    Case 7
                        TextBoxStatus.Text = "Programmable logic is not executing (Idle/Program Mode)"
                End Select

                If Val(bitString(8)) = 1 Then
                    TextBoxFault.Text = "Recoverable Minor Fault"
                ElseIf Val(bitString(9)) = 1 Then
                    TextBoxFault.Text = "Unrecoverable Minor Fault"
                ElseIf Val(bitString(10)) = 1 Then
                    TextBoxFault.Text = "Recoverable Major Fault"
                ElseIf Val(bitString(11)) = 1 Then
                    TextBoxFault.Text = "Unrecoverable Major Fault"
                End If

                Dim modeSwitch As UInteger

                For i = 12 To 13
                    If bitString(15 - i) = "1" Then
                        modeSwitch += 2 ^ (i - 12)
                    End If
                Next

                Select Case modeSwitch
                    Case 1
                        TextBoxKeyswitch.Text = "Keyswitch in Run Mode"
                    Case 2
                        TextBoxKeyswitch.Text = "Keyswitch in Program Mode"
                    Case 3
                        TextBoxKeyswitch.Text = "Keyswitch in Remote Mode"
                End Select

            ElseIf e.TransactionNumber = AttributeReadDeviceProductCode Then
                Dim ProductCode As UInteger = e.Values(0)

                Select Case ProductCode
                    Case 3
                        TextBoxProductCode.Text = "(Code 3) ControlLogix5550"
                    Case 15
                        TextBoxProductCode.Text = "(Code 15) SoftLogix5860 1789-L60"
                    Case 40
                        TextBoxProductCode.Text = "(Code 40) ControlLogix5550 1756-L1"
                    Case 41
                        TextBoxProductCode.Text = "(Code 41) FlexLogix5433"
                    Case 43
                        TextBoxProductCode.Text = "(Code 43) CompactLogix5320 1769-L20"
                    Case 44
                        TextBoxProductCode.Text = "(Code 44) CompactLogix5330 1769-L30"
                    Case 48
                        TextBoxProductCode.Text = "(Code 48) PowerFlex with DriveLogix5720"
                    Case 49
                        TextBoxProductCode.Text = "(Code 49) PowerFlex with DriveLogix5725"
                    Case 50
                        TextBoxProductCode.Text = "(Code 50) ControlLogix5553 1756-L53"
                    Case 51
                        TextBoxProductCode.Text = "(Code 51) ControlLogix5555 1756-L55"
                    Case 52
                        TextBoxProductCode.Text = "(Code 52) PowerFlex with DriveLogix5730"
                    Case 53
                        TextBoxProductCode.Text = "(Code 53) Studio 5000 Logix Emulate"
                    Case 54
                        TextBoxProductCode.Text = "(Code 54) ControlLogix5561 1756-L61"
                    Case 55
                        TextBoxProductCode.Text = "(Code 55) ControlLogix5562 1756-L62"
                    Case 56
                        TextBoxProductCode.Text = "(Code 56) ControlLogix5563 1756-L63"
                    Case 57
                        TextBoxProductCode.Text = "(Code 57) ControlLogix5564 1756-L64"
                    Case 64
                        TextBoxProductCode.Text = "(Code 64) CompactLogix5331 1769-L31"
                    Case 65
                        TextBoxProductCode.Text = "(Code 65) CompactLogix5335E 1769-L35E"
                    Case 67
                        TextBoxProductCode.Text = "(Code 67) GuardLogix 1756-L61S"
                    Case 68
                        TextBoxProductCode.Text = "(Code 68) GuardLogix 1756-L62S"
                    Case 69
                        TextBoxProductCode.Text = "(Code 69) GuardLogix 1756-LSP"
                    Case 72
                        TextBoxProductCode.Text = "(Code 72) CompactLogix 1768-L43"
                    Case Else
                        TextBoxProductCode.Text = String.Format("(Code {0}) Not Defined", ProductCode)
                End Select

            ElseIf e.TransactionNumber = AttributeReadDeviceName Then
                Dim StringLength As UInteger = e.Values(0)

                Dim index As Integer
                Dim Identity As String = ""
                While index < e.Values.Count - 1 AndAlso index < StringLength
                    Identity &= Chr(e.Values(index + 1))
                    index += 1
                End While

                TextBoxDeviceName.Text = Identity
            ElseIf e.TransactionNumber = AttributeReadDeviceSerialNumber Then
                Dim SerialNumber As UInteger = e.Values(0)

                TextBoxSerial.Text = SerialNumber
            End If
        End If
    End Sub

You could also try getting the device type/vendor name, should be attributes (1, 1, 1) and (1, 1, 2), but would have to check "device" and "vendor" listings here:

   https://github.com/dmroeder/pylogix/blob/master/pylogix/lgx_device.py

You could simplify these listings by only using the entries that are relevant to your setup.
The approach would be fairly similar to the "Product Code" section of the above code.

4
AdvancedHMI is currently rather difficult, if not impossible, to port to Android.
Archie did provide instructions on using Remote Desktop app here:

    https://www.advancedhmi.com/forum/index.php?topic=1278.0

There is also another open source library that can be used for communicating with PLCs (libplctag C library).

Here is the link to my Android Studio projects, with tablet and phone apps that allow for testing communication with Allen Bradley and/or Modbus PLCs:

     https://github.com/GitHubDragonFly

All it takes is to:
- download and install Android Studio
- download and extract the zip file from either of the projects available on the above link
- open this as an existing project in Android Studio and do a Build/Rebuild Project
- locate created APK file in this folder: app/build/outputs/apk/free/debug
- Copy the APK over to your tablet/phone and install it (you might need to enable the "Install from Unknown Sources" option)

Lots of old devices should be able to run the app since it was designed for Android 4.1 (API level 16) as minimum requirement.

In order to make any changes to the project, you will have to familiarize yourself with Android Studio and programming in java.

Attached here are a tablet and a phone screenshots, which are also included in the projects.

Archie was kind enough not to object to my posting this information here.

5
Tips & Tricks / Add a new or replace the existing control/component in AHMI
« on: September 05, 2020, 05:57:09 PM »
- Make sure you can see the Solution Explorer in your Visual Studio window. If you don't see it then press Ctrl+Alt+L or click "View" on the top menu and select Solution Explorer (see the attached picture of what you should be looking at).

- You need to know where that new control/component vb file is located on your computer

- You need to know either where you want to put the new or where the existing control/component is so you can replace it. Standard folders are located inside the AdvancedHMIControls project and would be either of Components / Controls / PurchasedControls. You can also create new folders/subfolders.

- Right click the folder of your choice and on the popup menu point to "Add" and then click "Existing Item", browse to the location of your new file and double click it. IF the Visual Studio pops a message asking if you want to replace the existing file always choose Yes.

- Close all open forms and rebuild the solution

If, by any chance, the PurchasedControls folder gives you an error then use Windows Explorer, go to your AdvancedHMIControls project and if it's not there then create it and repeat the above steps.

6
All of the related code can be found here:

   https://www.advancedhmi.com/forum/index.php?topic=2563.msg16238#new

It has somewhat unorthodox approach, which is to embed the unmanaged dll file as a resource and create a standalone exe file as the output.

Once run, the app will create a copy of the embedded dll file in the application folder, load it in memory when first needed and delete the file when the app is closed. All this is handled within the ApplicationEvents.vb / Program.cs file.

One could possibly use Windows\Temp or some other folder to copy the unmanaged dll files to, but would need to make sure that all the DLLImports, for the functions inside the unmanaged dll files, contain the full string path.




7
All of the related code can be found here:

     https://www.advancedhmi.com/forum/index.php?topic=2567.0

The idea behind this is to create a standalone executable file, which can be placed even on the desktop, without thinking of where all the required dll files are. Not recommended for AdvancedHMI solution since you can break something.

This idea could be described with these steps:

1) Add dll files as existing items to the project's Resources under Files (see the attached picture as an example of how to get there)
2) Add a reference to each of these dll files now located in the "Resources" folder
3) For each of these newly created references, set the Copy Local property to False
4) Resolve and load these assemblies with the handler added to the ApplicationEvents.vb file for VB and to the Program.cs file for C#

Step 3) is kind of optional since it doesn't affect the resulting exe file being standalone (if the Copy Local is set to True, it will only copy those dll files to the Debug folder but the exe file can be moved or copied to a different location all by itself).

This works but there might be a better way of doing this.

The example code, from the link mentioned above, has 3 dll files handled this way - Modbus.dll, log4net.dll and Unme.Common.dll.


8
For those who might be using the AdvancedHMIcs project as the main project, in order to have access to the FormChangeControls and MainMenuDriven controls then just download the attached file to add these controls.

You will need to create the same folder structure in the AdvancedHMIcs project, meaning create the FormChangeControls folder and then create the MainMenuDriven sub-folder.

Then add as existing item to corresponding folders each of these 4 files ( ONE-BY-ONE ) :

FormChangeButton.cs, FormChangeImage.cs, MainMenuButton.cs and MainMenu.cs.

Don't add any other files since they will be imported automatically.

In order to start the app with the MainMenu, modify the following line in the Program.cs file:

            Application.Run(new MainForm());
to
            Application.Run(new MainMenu());

You should also consider having this code behind the MainForm, just in case if this form is set as the startup form and a user is to click its "X" button:

Code: [Select]
namespace AdvancedHMICS
{
    public partial class MainForm : System.Windows.Forms.Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        //*******************************************************************************
        //* Stop polling when the form is not visible in order to reduce communications
        //* Copy this section of code to every new form created
        //*******************************************************************************

        private bool NotFirstShow;
        private void Form_VisibleChanged(object sender, System.EventArgs e)
        {
            //* Do not start comms on first show in case it was set to disable in design mode
            if (NotFirstShow)
                AdvancedHMIDrivers.Utilities.StopComsOnHidden(components, this);
            else
                NotFirstShow = true;
        }

        //***************************************************************
        //* If MainMenu is active then hide this form, else
        //* .NET does not close hidden forms, so do it here
        //* to make sure forms are disposed and drivers close.
        //***************************************************************
        private void MainForm_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            bool mainMenuActive = false;
            foreach (System.Windows.Forms.Form frm in System.Windows.Forms.Application.OpenForms)
            {
                //* Check to see if the MainMenu is a form in the list
                if (frm.Name == "MainMenu")
                {
                    mainMenuActive = true;
                    break;
                }
            }
            if (mainMenuActive)
                this.Hide();
            else
            {
                int index = 0;
                while (index < System.Windows.Forms.Application.OpenForms.Count)
                {
                    if (System.Windows.Forms.Application.OpenForms[index] == this)
                        index += 1; //* Do not force close this form
                    else
                        System.Windows.Forms.Application.OpenForms[index].Close();
                }
            }
        }
    }
}

For this particular code, you would need to open the MainForm in the designer and in its Properties window click the lightning bolt icon and make sure that the VisibleChanged and FormClosing events have the corresponding sub listed next to it.

FYI, the MainMenu can be positioned on the Top / Left / Right / Bottom of the screen. This is determined by setting the property "MenuPosition" and shaping the form itself (Width vs Height). Currently, the form to be opened will be stretched in one direction to fill the screen size.


9
Additional Components / Fan control
« on: April 10, 2020, 01:09:04 AM »
As for the fan control that has both CW and CCW direction, you could try using the attached control.

The direction is controlled with PLCAddressDirection and the fan is turned on/off with the PLCAddressValue.
See the description attached to these properties.


10
Additional Components / ComBridge2 component
« on: April 03, 2020, 11:58:36 PM »
Related to this topic:  https://www.advancedhmi.com/forum/index.php?topic=2532.0

For bridging multiple addresses try using the attached ComBridge2 component.

You would normally add your 1st PLC's addresses to the PLCAddressValueItems collection.
The trick is to use the "Name" property of each address to input the 2nd PLC's target address to write.

If you set the NumberOfElements value to higher than 1, for any address, then all the received values for that particular address will be written to the range starting with the target PLC's destination address.

A simple test could be performed with, for example, 2 instances of a Modbus simulator (one using TCP and the other using RTU mode with a pair of virtual COM ports or maybe both using TCP mode but on different ports).


11
Tips & Tricks / Troubleshooting with Breakpoints
« on: February 19, 2020, 03:58:31 PM »
Always use breakpoints for troubleshooting especially when you know at what line of code the program stops with an error.
Hover the mouse over the variables at the line and on the lines above, to see what values they have.

You can put several breakpoints and follow the flow of the execution by pressing F11.

The attached picture shows an example of using these, where red dots are the breakpoints.
The yellow highlighted line is where the program execution is currently.
The lines below the highlighted line have not been processed yet but the variables in these lines could still show some value.

Use Google to find out more about the breakpoints.


12
Tips & Tricks / SQLite Database Example
« on: January 26, 2020, 05:35:58 PM »
This is just an example that shows one possible way of using SQLite (purely for learning purposes).

The solution is in the attached SQLite.7z file but you will need to get SQLite.Interop.dll files and add them to the x64 and x86 folders.
You could find these dll files still available in the solution provided here:

   https://www.advancedhmi.com/forum/index.php?topic=1813.msg17141#msg17141


The attached pictures show what it looks like.
It has 2 tables, one for current customers and the other for archived customers.
Id is unique for any customer and will be archived as such.
The 1st picture shows all customers just before 3 of them were archived.

All that this solution will allow you to do is:
- Add a new customer
- Edit current customer's record
- Archive current customer
- Search for a customer within either current or archived customers
- Export either data table to a .csv file

Columns can be added or removed and the whole solution could be converted maybe for parts database or something else.

Any data in the attached pictures is made up and the solution might have bugs.

You can find another example of using SQLite in the "Application Showcase" category, posted by Phrog30, for alarming & history.


13
Additional Components / SerialToIPGUI app (VB Net version)
« on: December 27, 2019, 06:08:13 PM »
Moved here from other category & topic ( https://www.advancedhmi.com/forum/index.php?topic=899 ) for better visibility.

Original C# project can be found here: https://sourceforge.net/projects/serialtoip/?source=directory

It functions as an Ethernet-to-Serial converter (and vice versa).

The attached picture shows what it looks like while bridging communication between Modbus Master using RTUoverTCP protocol and Modbus Slave Simulator using RTU protocol. A pair of virtual COM ports was used as well: COM4-COM12 (by com0com program). All of these running at the same time on the same PC.

Showing the packets should be used only for troubleshooting since it slows down the program.

Attached is the full solution.


14
Some of you might find it useful and the attached picture shows what it looks like.

Get it here:  https://github.com/GitHubDragonFly/Number_Type_Converter

Windows Ms Calculator in Programmer Mode offers lots of these features and can be used to double check the accuracy.


15
Additional Components / Modbus Master and Modbus Slave Simulator apps
« on: November 30, 2019, 09:20:19 PM »

Offered AS IS.
Intended as a quick testing tool.
Can be tested as they are, see reply #3.


Moved here from the other category and topic (https://www.advancedhmi.com/forum/index.php?topic=765.15) for better visibility.

Both apps are based on modified nModbus .NET 3.5 libraries, Copyright (c) 2006 Scott Alexander ( https://code.google.com/p/nmodbus/ ).
Licensed under MIT license ( http://opensource.org/licenses/mit-license.php ) and included in the Project.


Modbus Slave Simulator

This is a new version of the Modbus Slave Simulator previously discussed in the topic mentioned above.

Now supporting RTU, TCP, UDP and ASCIIoverRTU protocols.

For RTU/ASCIIoverRTU protocols, on a single PC, AHMI can communicate with this simulator with the help of the tty0tty (Linux) / com0com (Windows) program which would provide virtual serial port pairs.

Since the DataGridView controls, used to display boolean/register values within the simulator window, seem to require rather fast computer, all instances were limited to initially have only 20 rows showing thus limiting the number of visible addresses (which should still be sufficient for simulation but can be changed and increased via the "Row Count" combo box). This has improved the speed of loading of the program in Mono on slower PCs.

The simulator will still accept ALL the Read/Write requests for ALL the registers and keep the values stored in the slave's dataStore. They will just not be visible in the data grid view, unless you choose to have all the rows visible.

There is also a TextBox added to allow for manual input of the serial port to be used (intended for Linux so tty0tty virtual ports could be accessed).

All the simulation was tested in:
- Windows 7/10
- Kubuntu 14.04 Linux on an old HP TC1100 Tablet PC, with 1.2GHz Pentium-M CPU and 1.25GB RAM.
- Raspbian Buster on RaspberryPi 2

The library supports Masked Bit Write, function code 22 (0x16H).


Modbus Master

It has the library built in support for RTU, TCP, UDP, RTUoverTCP, RTUoverUDP, ASCIIoverRTU, ASCIIoverTCP and ASCIIoverUDP protocols (not all of them were tested).

It also supports F, L, U, UL and S modifiers as well as bit/character Reading/Writing.
For bit/character operation, you can select to have it either as consecutive bits/characters within a single element or the exact individual bit/character from each of the multiple elements.
Either a single value or the exact number of comma separated values will be required for writing if Points number > 1.

A support for 64-bit values was added - Double (Float64), signed and unsigned Integer64 (Long and ULong).
Modifiers of FQ, LQ and UQ were added to the Master app, where "Q" stands for Quad Word.

A support for 128-bit values was added - signed and unsigned Integer128.
Modifiers of LO and UO were added to the Master app, where "O" stands for Octa Word.

SwapWords option, if enabled, might present a challenge for some devices since these things don't seem to be officially defined.
Just try either of the 3 options provided for 64-bit values word order or any of the 7 options provided for 128-bit values word order (theoretically, there should be far more than 7 options available but I didn't bother going through all of them).

The library supports Masked Bit Write, function code 22 (0x16H), but the app also includes the built-in code for slave devices that don't support FC22.
The built-in code will read register - modify the bit - write register, which could affect the bit values that changed during this operation.
Either of these apply to all values (16-bit, 32-bit, 64-bit, 128-bit).

Addresses do NOT have offset of +1.

The "Auto" checkbox allows for Automatic Readings with poll interval specified in the "Interval" box.
If you add a new address to read after the "Auto" box is checked then you will have to uncheck it and check it again.

It is intended for quick testing but always try using AdvancedHMI as a Modbus Master instead, since it offers far more features and functionality.

Read the comments inside the form and also hover the mouse over the labels since most of them do provide hints.


This post has VB Master solutions attached (for Windows and Mono).

Pages: [1] 2 3 4