From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

ACTOR Framework and MODBUS

So, I am working on implementing an Actor Framework to be used in a system I have that is simulating real hardware. So, it will have a few actors that run independently, but will need to communicate with another controller that is reading/writing to the MODBUS registers.   I am getting lost as to how I can share this MODBUS resource across all my actors. I don';t want each one of the actors to have their own modbus server. I have one modbus server that I will use among them. Any thoughts?

0 Kudos
Message 1 of 9
(7,223 Views)

Encapsulate the server API into an Actor and send messages to it. You'll probably want the statefulness of an Actor wrapping the calls anyway, to prevent several components from making conflicting calls.

Message 2 of 9
(4,988 Views)

When you say encapsulate, you mean to add the MODBUS server as an Actor?  I create a class with the MODBUS server API (just using the simple version not the DSC version) and inherit from ACTOR?

0 Kudos
Message 3 of 9
(4,988 Views)

Modbus is a protocol that can be implemented with Serial or TCPIP (to name a couple); this allows the same protocol to have different transport implementations.

The actor should encapsulate the resource (i.e., the controller) to the real hardware; a child simulation actor could then override the approriate methods of its parent real actor to provide simulation.

0 Kudos
Message 4 of 9
(4,988 Views)

I plan to use the MODBUS TCP/IP.  I am using an PXIE Chassis. So, I will have an actor that will be working with the PXIE Chassis and then use a child actor to override the necessary methods?

0 Kudos
Message 5 of 9
(4,988 Views)

Your real actor should use a TCPIP implementation of the Modbus protocol; your simluation implementation of the real actor would override methods that would affect the real hardware and provide a simlated solution.

The end result is that the simulator will handle all the simulation and will not be talking Modbus TCPIP to anything.

Consider that in this architecture, if you choose to change the transport from TCPIP to Serial, all you would need is the Serial implementation of the Modbus protocol.

0 Kudos
Message 6 of 9
(4,988 Views)

So they way to think about it is make your ModBus Server is own actor.  It handles all the resources for your Modbus connection.  It establishes the connection, and reads and writes all the registers.  Your other actors communicate with actor, by sending it messages and receiving messages back from your ModBus actor. 

There are a couple of ways to build your ModBus actor and honestly this is where I always struggle, since in general you want your Actor to always be responsive, but TCP or Serial connections inherently have a timeout that can occur if connection is lost or there is a delay in reading/writing.

Either way I would start where the others suggest: Build a Class Hierarchy for your ModBus Server.  Have a generic Modbus class that has an abstract method for every action you need to do.  Then make two children classes (Serial/TCP) that override your methods to perform the actions based on your communication method. 

The next step is where things can get tricky.  Here you will have to decide how responsive you want your system to be. Honestly I struggle with this so hopefully people have some advice on how to handle Actors with Timeouts and waits in their methods.  At some point you have to do the actual work and your actor may lock for a bit. 

     1) You can have this ModBus class inherit directly from the Actor Framework.  If you do so, then exposing its queue to other actors will allow you send messages directly to      it.  But doing so means that if you lose TCP connection your actor queue may start to back up and become less responsive.  It’s the easiest and quickest way to get your      actor up and running.

     2) Another option is to build a new actor class, lets call it ModbusController, that encapsulates your Modbus class. Within the Actor Core of this controller class, you could      have a separate loop that does the “actual work” on your Modbus class(I would not have Modbus inherit from Actor in this case).  In this case, you would have to write      separate methods for your Controller that would act on a DVR,Queue, Event or Notifier that would pass info to your Helper Loop and actually perform the modbus actions.      The controller is also responsible for monitoring the State of your Modbus class and filtering messages to it based on its state (IE: connected, disconnected….).

     I tend to prefer this option to #3 because at the end of the day you have a non-actor class, Modbus, that can be used in other projects without being modified if they don’t      rely on the actor model. However, it feels super heavy from a programming standpoint.  It’s a lot of legwork for extra responsiveness that may not even matter in some cases.

     3) Build a ModbusController Actor as above, then have it launch a Modbus Actor, as in #1 and have your Modbus Controller filter info into Modbus Actor.  This to me feels      like I’m making my Modbus Actor queue just a job queue that the ModbusController works on.

     For me I always struggle with the actor framework b/c I want to think about a Hardware Object as an actor, when really it’s probably best to abstract another layer on top of      that Object that serves as a “Controller” for the hardware is it what handles all the messages.  It’s a very easy way to get a QMH up and running, but it gets very heavy very      quickly.

I’m struggling to figure out if the extra layer of abstraction for a “Controller” is worth the extra code.  It just depends on how flexibly you need your code to be.  I might be abstracting WAY too much and just need to right better base classes. 

I also tend to mix and match things within the Framework and not uses messages for every item.  I often have actors read and write to a common database, or a Varient Lookup Table stored in a FG, instead of sending direct update messages.  This goes directly against the spirit of the Actor Framework, but the time it takes to write Hierarchal messages for every data updates can be cumbersome and very code heavy.  In some cases i have switched back to the CaseStructure/String Messages Actor Template that Daklu posted on Lavag, soley b/c its less heavy.

I figured I’d give you a wall of text to maybe help out some and lay out my own thoughts.  Hopefully some of it helped.

Message 7 of 9
(4,988 Views)

What is your class design? If you constrain the class hierarchy to Actor <|-- ModBus <|-- AnalogSensor, how would you implement AnalogSensor to use a Wago controller?

In our designs:

- DeviceActors model physical resources (e.g., Motors, Switches, Cameras, Sensors, etc.);

- ControllerActors encapsulate vendor provided APIs that directly access physical hardware e.g., Aerotech, Newport, Wago, etc.);.

- CommunicationControllerActors encapsulate the management of a Communication connection (e.g., serial port, TCPIP address, socket, etc.) to the physical resource with a Protocol (e.g., ModBus, vendor defined character sequences, etc.)

This allows us to connect DeviceActors with ControllerActors or CommunicationControllerActors using the adapter pattern. In this way a Motor device can be adapted (with not extra code except the adapter code) to work with an Aerotech or Newport ControllerActor or a ModBusSerial or ModBusTCPIP CommunicationControllerActor.

Message 8 of 9
(4,988 Views)

I've written a few AF apps for controlling environmental chambers that amongst other things talk using Modbus to third-party embedded controllers, using the DSC module's I/O Server. My 'test controller' actor sends a message to the 'plant actor' along the lines of 'Turn Plant On', the message calls a method which writes to the appropriate Modbus register.  I can then easily override the method to use different modbus addresses for different chambers for example, or provide a simulation option etc. 

Message 9 of 9
(4,988 Views)