Home / C# / Using AdvancedHMI’s PLC drivers with C#

Using AdvancedHMI’s PLC drivers with C#

AdvancedHmi is a free and “almost open-source” HMI framework written in VB.Net that offer some drivers for PLCs, and also offer free SCADA objects for winforms users.
I say “almost open-source” because the code of the two main libraries is not provided (MfgControl.AdvancedHMI.Drivers.dll and MfgControl.AdvancedHMI.Controls.dll), but it’s provided how to use them.
What is really good about AdvancedHMI is the easy interface that the drivers offers, that doesn’t change when you change the driver, so you can make the same HMI and using different drivers without much problems.

The drivers

AdvancedHMI contains those drivers:

  • Rockwell Automation (Allen Bradley) Controllogix and CompactLogix ethernet/IP driver
  • Allen Bradley SLC, MicroLogix, PLC 5 serial and ethernet driver
  • OPC Client
  • Modbus TCP
  • GE Fanuc SNP-X serial port driver
  • Siemens PPI driver

Every driver implement this interface:

public interface IComComponent
{
	public delegate void ReturnValues(string[] values);
	int Subscribe(string plcAddress, Int16 numberOfElements, int pollRate, ReturnValues callback);
	int Unsubscribe(int id);
	string ReadAny(string startAddress);
	string[] ReadAny(string startAddress, int numberOfElements);
	string WriteData(string startAddress, string dataToWrite);
	bool DisableSubscriptions { get; set; }
}

and we need those methods:

	string ReadAny(string startAddress);
	string[] ReadAny(string startAddress, int numberOfElements);
	string WriteData(string startAddress, string dataToWrite);

As you can see we can read from an address with the ReadAny method getting PLC values as strings or array of strings, then we can convert them to bool, int, float and so on using the Convert class.
To write is even simpler because you just have to call the method WriteData, providing the address and the value.

Import the library

To create a driver we just need to import the project as reference (or build the dll and import as reference).

Create a driver object

To create a driver object you have to choose the driver. For example let’s say that i want to communicate with a Micrologix1400 via Ethernet/IP.
So i create my plc object in this way:

//at the beginning you must declare
using AdvancedHMIDrivers;

[...namespace and class declaration and so on ...]

//create the object
EthernetIPforSLCMicroComm MyMicroLogix = new EthernetIPforSLCMicroComm();

public MainWindow()
{
     InitializeComponent();

     //assign IP
     MyMicroLogix.IPAddress = "192.168.0.5";
}

Read and Write

Then it is needed to create a timer to read and write.
For this example i use WPF’s DispatcherTimer, but you can use what you prefere.

DispatcherTimer timerReadPLC = new DispatcherTimer();

public MainWindow()
{
     InitializeComponent();

     //assign IP
     MyMicroLogix.IPAddress = "192.168.0.5";

     timerReadPLC.Interval = TimeSpan.FromMilliseconds(200); //every 200ms update
     timerReadPLC.Tick += new EventHandler(timerReadPLC_Tick);
     timerReadPLC.Start();
}

//timer callback
void timerReadPLC_Tick(object sender, EventArgs e)
{
    label1.Content = MyMicroLogix.ReadAny("B3:0/1"); //bool
    label2.Content = MyMicroLogix.ReadAny("N7:0");   //int
    label3.Content = MyMicroLogix.ReadAny("F8:0");   //float
}

To write i use callbacks:

private void button1_Click(object sender, RoutedEventArgs e)
{
    MyMicroLogix.WriteData("N7:0", 1);
}

Where my User Interface is like this:

Documentation

If you browse the solution you will find many documents that explains how to use drivers and how to setup simple examples of applications.

Download the sample

You can download the sample application at this link.
The sample application is provided with all the dlls that you need to make it work, anyway you should download the newest version of AdvancedHmi, compile it and get the newest dlls if you intend to use it separately from your project. Remember that the project MUST be open-source (because of GPL license, check the next paragraph for explanation).

Pro and cons of using AdvancedHMI

PRO

  • Quick results: with little code you are able to read and write from a PLC without much problems, so if you are approaching to SCADA with .Net, AdvancedHMI should be your 1st step for communicating with PLC.
  • License is fair: About the GPL license, you must give the source code of your application on demand. In short words, it’s a “derivative work” license, so if you use a GPLed library to write a program (AvancedHmi), the “customer” must be able to recompile it if he need to.
    This means that you can integrate your own dlls to protect your know-how, but you can’t keep the program closed source (dlls closed-source are ok if they don’t use the GPL library, the main project must be open). This is common to every other HMI and SCADA on the market by the way.
  • Support: AdvancedHMI support is at payment, but they offer training, customization and also a development service. It’s a good point that an open source project offer a support service, because it means that you will not be abandoned if you will encounter problems.
    If you don’t want to pay you have to wait for the next version for bug fixing. But they will fix the bug, for free.

CONS:

  • drivers are closed source: if there is a bug (and it happened to me) you need to wait for the new version (check the support forum on sourceforge to have an idea).
  • Some drivers are in “alpha stage”: for example the OPC Client that instead of subscribing is adding and removing items at every read (at least in 3.21b).

I reccomend AdvancedHMI

I really reccomend AdvancedHMI for starters in communication with PLCs, so you can setup your application quick and without spending too much time on the PLC communication.
Advanced users (and for advanced i mean peoples that can write protocols, reverse engineering and so on) should check open source libraries, but anyway the advanced user is not the target of AdvancedHMI, despite his name :). AdvancedHMI should be used to get quick result and to develop cheap (0$) and good looking HMI in short time.
You can download AdvancedHMI and the drivers on the sourceforge site.
The programmers of AdvancedHMI also host a website where you can get information and also a youtube channel with a lot of tutorials.

59 comments

  1. I’ve been using AdvancedHMI for a while now. You didn’t mention that it comes with a TwinCAT ADS driver for Beckhoff TwinCAT PLCs, and I’ve modified the driver to work with TwinCAT 3. The flexibility of AdvancedHMI is it’s strong point. I was also able to modify all the HMI controls to include a built-in authentication check, so I can, for instance, limit a pushbutton to only be accessible to a supervisor, simply by setting a property of the button itself. Without having he source code available, this would have been very difficult.

    I was also surprised how good the performance was. Using the TwinCAT ADS drivers the HMI is very responsive, much better than what you’d be used to with a traditional PanelView-like HMI.

    • Archie Jacobs removed the TwinCAT driver (TwinCATComm.vb) in the latest release. Don’t know why, because in the changelog it wasn’t reported.
      Anyway it’s a good project and visual controls are “wow”, but it’s a sad fact that it doesn’t support WPF. Also there are some choices that i can’t understand, like “rewriting modbus protocol” when there are tons LGPL or BSD, just to embed it in the closed source dll.

      • As an FYI…. The TwinCAT driver was removed from the project for multiple reasons. The native driver (pure .NET version) used the TCP/IP stack therefore could not be used on the same PC that TwinCAT was running on. For this to work, it was necessary to pass everything through the AMS router. Beckhoff was not willing to give the information on how to interface to their AMS router without using their DLL. Their licensing of the DLL does not allow it to be distributed with an open source project, therefore would require many steps in order to incorporate the driver based on their DLL.

        Since all of these scenarios generate a lot of support inquiries, it was decided to no longer support TwinCAT until the information on the AMS router can be obtained to make the native driver work in all scenarios or permission from Beckhoff was obtained to distribute their DLL.

        Since AdvancedHMI is a free package and is mostly targeted toward non to less advanced programmers, providing software that requires little to no support is the key to its success. Logic will tell anyone that free software and free support is not sustainable.

        • The support that AdvancedHMI offers is definitely a pro, never said that the support should be free.
          Archie, you did a good job with this program. I also started from AdvancedHMI two years ago. I wish you to have success!

        • It’s hard to believe it has been over 4 years since this was posted, but I wanted to give an update about the subject of the TwinCAT driver. It is once again part of the ongoing releases. However it still suffers from the one weakness of not being able to run on the same PC as is the TwinCAT it intends to communicate. The driver has been much improved and when version 3.99p becomes available, the driver will even start up faster. Thanks to all the users for the feedback that has made AdvancedHMI continue to grow into an even more powerful platform.

  2. I’d really like to see something available for the relatively new S7-1200 series from SIEMENS. You’ve talked about the free SIEMENS libraries for some time most of those haven’t been updated since 2010 and I don’t yet know if its worth the time investment to develop an application around those libraries for unsupported hardware.

    Thanks for this, though, I am quickly learning that there is actually more free software out there for PLC/SCADA than I thought.

    Keep up the good work.

  3. Hi Derek, i think that for Siemens S7-1200 the best way is to use Modbus TCP if there is the Profinet (ethernet) port, or Modbus RTU. Check the article here: https://www.mesta-automation.com/modbus-with-c-sharp-libraries-examples/ .
    About how to configure Modbus on Siemens PLC, you should check Siemens site: http://www.automation.siemens.com/WW/forum/guests/PostShow.aspx?PageIndex=1&PostID=367004&Language=en .
    Unfortunately i don’t have the hardware to make an article. For Allen Bradley Micrologix 1400 i had so i could post how to configure. You can check that article to have an idea on how Modbus works at PLC side.

    About the libraries that aren’t updated since 2010, you should realize that some libraries like LibNoDave are a “standard de-facto”, because they are used in many applications and trusted a lot. Also it’s not that Siemens can change the protocols and discountinue all S7 plcs becuase someone reverse-engineered the protocol. So yes, those libraries can be trusted especially because they are open-source.

  4. I have a simple ADAM 6156 hardware, i arrive to connect and get an outpout value with : _EthernetIPforPLCSLCMicroComm.ReadAny(“B0:0/1”); i get a “False” reponse. But when i try to write with _EthernetIPforPLCSLCMicroComm.WriteData(“B0:0/1”, “1”); i get an error “No Data Returned”,

    I new in that maybe is a configuration problem.

    Thanks in avance..

    • Hi Ruben, you should try the EthernetIPforCLXComm driver instead of EthernetIPforPLCSLCMicroComm.
      The EthernetIPforCLXComm is the real ethernet/ip driver that uses the CIP protocol, the one used by ControlLogix and CompactLogix family.
      The EthernetIPforPLCSLCMicroComm is the old DF1 (PCCC) protocol incapsulated in ethernet/ip, it’s a similar communication of the 1747-NET-ENI, and it should be used only to communicate with old Allen Bradley PLCs (Micrologix, SLC, PLC5).

      Also try to write _EthernetIPforCLXComm.WriteData(“B0:0/1?, 1); removing the quotes from the value, maybe it can solve your problem.
      Oh and i never noticed in a SLC – Micrologix the address B0:0/1. I Always knew that address 0 was for Output and address 1 was for Input, Address 2 was for System file and you started from B3:0 – T4:0 and so on.

  5. Dear Mesta.
    Is possible to use the graphic object controls in c# instead of vb.net ?
    I alredy try to add reference to all advanced hmi dlls but the controls doesn’t appear in the toolbox

    • @AutomationGuy:
      With advancedHmi is not enough to add the dlls for the visual controls, you need to add the entire project as reference.
      When you download the project from sourceforge, inside that project you can create your own c# project (if you have the VS professional or more) and then add the AdvancedHmi project as reference.

      The other way, more complex, is to translate from VB to C# all the visual controls contained in the folder Controls inside the AdvancedHmi project.
      When you translate the controls you will get them added to the toolbox.
      The dll are only hiding the sources and images that are behind the controls.

  6. Hi,
    How to use RS232/COM port data in Advanced HMI? Which driver should I need to use? thanks

    • If the driver that you need is not included in AdvancedHmi, you probably need to use the SerialPort class of .Net and build your protocol manually.

      • Hi,
        Thanks for the reply. One more question, How can I use that driver for HMI controls?

        • Every HMI control has a property called Value. You make a timer in your codebehind and you update the control by setting the value inside the timer callback.

  7. Is there an easy way to restrict the number of decimal places an OpcDaCom1 driver can display? I figure it’s something to do with “NumericFormat” on for example the BarLevel control value. I can’t figure the syntax out for two/three decimal places. Any help would be appreciated. Thanks in advance.

    • I think that you can update the visual control in two ways: one is by using the automatic interface between the control and the drivers, and one is by code with the property value.
      If you have defined a driver, named “OpcDaCom1”, you can go on the Form designer, on the properties tab of the driver there is a single event called Data Received.
      Double click on it, it will create an handler and there you can insert a code similar to this

      Private Sub OpcDaCom1_DataReceived(sender As Object,
      e As Drivers.Common.PlcComEventArgs) Handles OpcDaCom1.DataReceived
      BarLevel1.Value = Math.Round(Convert.ToDouble(e.Values(0)), 2)
      End Sub

      • Hi Again, thanks for info & prompt reply. I managed to extract what I needed from your code example.
        Just out of interest, any idea what the “NumericFormat” is for in BarLevel and what syntax works with it?
        Thanks again in advance

        • Probably you can define there a string format, like “D2″ maybe, or”#.00”.
          However you better ask in the dedicated forum of advancedhmi.com, if you have issues on the “hidden code” or if there is a lack of documentation.

  8. I am getting this to work in ASP.NET but it only works for a short time. After several successful attempts I eventually get an error. sys.webforms.pagerequestmanagerservererrorexception. I am trying to use a Timer Control with a UpdatePanel and ScriptManager. I am trying to use this to get a post back every 5 sec.

    Has anyone used a different timer method to get a automated post back.

  9. Ok so if “MyMicroLogix.WriteData(“N7:0″, 1)”;

    With c# (asp.net) is there a simple way to latch(set) or unlatch(reset) a bit like b3:0/0 without the use of the toolbox items just with code?

    • The example provided doesn’t use the toolbox item. Did you check the example ?

      • Thank you for your reply. 🙂

        Yes I did check the example. I realize it does not use the toolbox and just uses code. With the code used in the c#wpf example I have written a c#ASP.net webform and uploaded it to a remote host. I can log into my webform with my blackberry from any where and read any address from the plc. I can write values like timer and counter preset. I can write N:7 values and strings but I can not latch(set) or unlatch(reset) bits or outputs. I was wondering if this was possible.

        • I don’t remember if there is a function to set or reset bits, however you can write the entire B3:0 word.
          Also you should try to write B3:0.1, instead of B3:0/1, because as i remember some drivers required it.

  10. when i declare like what you said :
    “public interface IComComponent
    {
    public delegate void ReturnValues(string[] values);
    int Subscribe(string plcAddress, Int16 numberOfElements, int pollRate, ReturnValues callback);
    int Unsubscribe(int id);
    string ReadAny(string startAddress);
    string[] ReadAny(string startAddress, int numberOfElements);
    string WriteData(string startAddress, string dataToWrite);
    bool DisableSubscriptions { get; set; }
    }”

    this is the error in C#
    Error: ‘ReturnValues’: interfaces cannot declare types

  11. An update has been made to AdvancedHMI. As of Version 3.80, it has been restructured to make it easier for C# users. You can now simply right click the solution and add a new C# project. The toolbox will be automatically populated for the C# project.

    • before i upgrade to ver.399a
      this one will work
      public static EthernetIPforCLXComm Cx = new EthernetIPforCLXComm()

      after i upgraded it shown the error

      the type or namespace name ‘EthernetIPforCLXComm’ could not be found

      anyone can help me

  12. Mesta, thanks for your post, it gives a transparent overview of using AdvancedHMI.
    I’ve found another example of open source C# HMI https://github.com/RapidScada/SCADA Does anybody use this software?

  13. Is possible a serial comm with a PLC Allen Bradley using C# to read a value?

  14. el contenidoes para VB y necesito advanced hmi para C#? saben algun link??

  15. nice tutorial, excellent. i have one question i getting error when i tried to read array, e.g. timerKO[0], timerKO)[1]….timerKO[n]..
    any idea how to read array in controllogix

    • As I remember, to read the arrays you have to specify the lenght that you want to read, something like:
      “ArrayName[0],L50” to read 50 items starting from index 0 of the array “ArrayName”.
      The best place for advices is the advancedhmi.com forum. It’s free and they will help you.

  16. dear mesta your site is wonderful and constantly i’m reading it because it has full of informations

    just few questions, if i have several tags how to auto update the values, without using the timers which you gave in your example?
    you have example for these?

    • These drivers just send a request to the plc, and the plc reply with values. This means that the only way to get values from the plc is by polling it in a cyclic way, and that’s why I use a timer.
      If you have a driver that support subscription, like OPC, you can do without timer.
      This example however is a basic example that just show how to read some tags and display in the application, but I usually make a PLC class, that contains all tags. In that class I have a timer that polls the plc and update all the tags with the timing that I need, and I declare that class a singleton so I can access to the tags from all the program. That’s what I usually do in HMI. This is a more advanced example that uses a singleton class: https://github.com/mesta1/S7.Net-example/tree/master/HmiExample

  17. I have AdvancedHMIDriver dll added to C# solution. When debugging in Visual Studio is working fine. The problem starts when I publish project. Lunching program fails with AdvancedHmi missing in AppData\2.0\1CALNN63.JGA\PE0PLHKA.QGH for prot..tion…… catalog on Windows 7 home. Any suggestions?

    • I’m sorry but I don’t have experience with ClickOnce, I use other installers. Try to check if all dlls are present in the folder after the installation, maybe you didn’t include something.

  18. I have a DLL which I need to add to AdvancedHMIDrivers so that I can communicate with a proprietary piece of hardware – it is essentially a certain particular data packet structure the device expects to see via an RS-232 port. I have the C++ code for the DLL which I have added into the AdvHMI project and it compiles, but I am not able to get a driver into the Toolbox to be deployed. I realize this has something to do with the particular class to which my DLL belongs, that it has to inherit the System.ComponentModel, but am not seeing how to get my C++ code into that class. In fact, whenever I try to create a new class diagram in my C++ project, dragging in the code from the solution Explorer, I get a fault “One or more of the selected items cannot be added to the class diagram.” I am almost at the point of going in and rewriting DF1DRV for my use, but it WOULD be nice if I could get this particular DLL (which works with OTHER Windows HMI packages…) to function with AdvHMI,
    Any advice

    • I don’t know with C++ how it works, but basically in C# you need to create a UserControl and add it to the toolbox. You can probably call your C++ dll from the C# UserControl, like AdvancedHmi does with MfgControl.AdvancedHMI.Drivers.dll, that contains all the drivers not open source.

  19. Hi, I need to acess PLC Allenbradley(Rockwell) with controlLogix
    because I need to get the name of a specific tag instead of using the MicroLogix, this is possible with the AdvancedHMI? Grateful.

  20. I want to create two instances of EthernetIPforCLXComm in different thread like that:
    Task.Run(() =>
    {
    EthernetIPforCLXComm MyMicroLogix1 = new EthernetIPforCLXComm();
    MyMicroLogix1.IPAddress = “192.168.1.3”;
    while (true)
    {
    String s1 = MyMicroLogix1.ReadAny(“Vision_Begin_Above”);
    Thread.Sleep(1000);
    }
    });

    Task.Run(() =>
    {
    EthernetIPforCLXComm MyMicroLogix2 = new EthernetIPforCLXComm();
    MyMicroLogix2.IPAddress = “192.168.1.3”;
    while (true)
    {
    String s2 = MyMicroLogix2.ReadAny(“Vision_Begin_Below”);
    Thread.Sleep(1000);
    }
    });
    then I got an error,but if the two instances of EthernetIPforCLXComm in a same thread,everythind is ok!Why? how can I create two instances of EthernetIPforCLXComm in different thread? Thanks

  21. how to create two instances of EthernetIPforCLXComm in different thread?

  22. Hi, I’m from Brazil and I tried to use AdvancedHMI. It works perfectly since it is run from within Visual Studio, while trying to run straight through the exe, the following error occurs: System.Exception: Missing Components from AdvancedHMI. D: \ plcc # \ test2 \ WpfApplication \ bin \ debug \ in MfgControl.AdvancedHMI.Drivers.EthernetIPforCLX.BeginRead ()

    I’ve tried to add directly into the project advandedHmi but the same error occurs. What can it be?

  23. System.TypeLoadException: ‘Could not load type ‘MfgControl.AdvancedHMI.Drivers.Common.TransactionNumber’ from assembly ‘MfgControl.AdvancedHMI.Drivers, Version=3.99.19.2, Culture=neutral, PublicKeyToken=null’.’

    this is my problem, what is solution?

  24. I have written few line to read a tag but it is throwing an exception “Please refer to the licensing agreement.”

    //create an object
    EthernetIPforCLXCom ethernetIPforCLXCom = new EthernetIPforCLXCom();
    DispatcherTimer timerReadPLC = new DispatcherTimer();
    ethernetIPforCLXCom.IPAddress = “192.168.0.10”;
    Thread.Sleep(1000);
    var test = ethernetIPforCLXCom.Read(“FC_210.hmi_data.CV.Value”, 1); //exception occurs

    Please let me know what needs to be done to resolve this.

    Any help would be appreciated.

Leave a Reply to Damian Cancel reply

Your email address will not be published.