Video demo on YouTube
This repository contains code with simple features like :
- Sending an email
- Sending a text message
- Sorting an array
- Making a REST API call
- Data persistance to a database
- Generated user interface
BUT with a PLC. PLC is an idustrial Arduino on steroids.
Unfortunatelly working with PLC is cumbersome.
PLCs were meant to replace physical wiring of relay logic - so it's more electrical engineering than software engineering.
So obviously it's not really good at software stuff
...unfortunatelly the industry forces you to write enterprise software in a PLC.
Beckhoff's TwinCAT 3 is one of few which offers modern features like object oriented programming, open API and integration in Visual Studio. Other platforms are using their own IDE with their own language.
Delivering features with PLCs is cumbersome. Sure, it is possible to deliver a complex feature in a PLC, but is it worth the hassle?
Dealing with a hardware configuration, reading through an obscure documentation just to find the specific memory address... Yuck!
WELL NOT ON MY WATCH!
Time is precious, let's not waste it.
I'll show you how to implement some features from Inxton's Advanced package with the Core package.
Let's start with the most powerful one. Funny enough, it's pretty simple to implement it.
I'll focus on the conceptual design. Here's the code :
-
TwinCAT function blocks - Github link
-
C# Twins/counterparts - Github link
PLC has the CSharpMethod
function block which encapsulates a simple logic. It also has a C# twin (a counterpart) generated by Inxton called CSharpMethod.g.cs
When the PLC sets the InvokeRequested
variable, its C# counterpart will notice and do the work on the PC side. It will also notify the PLC that the work started and ended.
So to call a C# method from a PLC I have to initialize the counterpart and set a variable in the PLC.
I will use the CSharpMethod
function block to send an email, because it's so much easier to do so in C# than in CoDeSys.
I created another function block fbEmail
which contains a subject, content and the recipient of the email.
It also contains a variable SendEmail
of type CSharpMethod
. This variable needs to be initialized in its C# counterpart.
Like this
SendEmail.Initialize(SendEmailMethod);
It says what C# method should be executed when PLC asks for it. Now you write the function which will send an email - which is rather simple.
Sending an email is possible with Beckhoff's TF6350 (source).
I consider the PC implementation in C# method to be simpler, easier to maintain and easier to extend in the future. Also it comes with no additional costs.
On the other hand the implementation in PLC is not that bad and there's no need to generate a Twin because of single email. You do need additional licence though.
Text message is similar to the email example.
You can use the same library, Beckhoff TF6350 (source) with an additional modules and a GSM modem and rather poor documentation.
Or you use a service like Twilio. Initialize the CSharp method with existing library from Twilio and you can send text messages within a few keystrokes...just for $0.0075.
I found this link on CoDeSys forum with sorting code in the PLC.
It's ridiculously complex and hard to read. And that's just for simple array of numbers. What if you want to sort array of structures?
Lucky for us it's really simple in C#.
Everyone understands what Array.Sort(plain.MyArray);
does
...But the first example above? not so much.
If you need to interact with a server, ERP or any other external application, there's a good chance you'll encounter REST API.
Again making the most out of the CSharpMethod
function block, we delegate this functionality to the C# Twin. C# is used a lot in the server-side world, where REST API is a first class citizen. That's why there's a library like Refit which makes interfacing 3rd party applications a breeze.
Using Refit, a sentiment analysis using machine learning solution was one API call away.
I generated C# classes from JSON, parsing was done automatically, and I just pushed the result to the PLC. Fast and lean.
Beckhoff offers TF6760 (source) for HTTP/REST communication. Again I find it more difficult to use, the amount of examples is not sufficient. I'm a bit worried about additional complexity of the code when HTTP Headers and different kinds of authorizations comes into the play.
The C# Twin comes with an unexpected benefit. It's possible to store entire objects of data into the database without any effort.
Inxton offers this functionality in the Advanced package, but it's possible to implement it by using open source alternative like like MongoRepository. You don't get any support or some extra features though.
I extended every structure I want to save with stEntity
and extended the C# counterpart stEntity.g.cs
with the class from MongoRepository.
Now I add an Entity
to my stSettings
structure, and my settings are stored in a database as easy as never before.
If the settings structure changes, just run the Inxton compiler again. That's it.
I'm not aware of a single PLC solution that has this functionality.
Generating user interface is bit more complex topic. But again, leveraging C# Twin you can use DataTemplating in WPF UWP, or code your own templating engine in ASP.NET.
I'm using Inxton Essential package and the provided RenderableContentControl
to generate whole PLC objects.
Now a single line of code will do the manual work of putting every single variable to the screen for me.
I also created a custom view for my fbCsharpMethod
so users can invoke the command from the user interface!
Again, I'm not aware of a single PLC solution that has this functionality.
It took me only an hour or two to implement all of these features. And I could go on and on...
These real-world problems are often solved inside a PLC brining unnecessary complexity into the project, causing many headaches.
In small projects, it's not a big deal.
But what used to be a simple machine few years ago, is nowadays an enterprise level software with moving parts.