Can I create Comm Device via a sequence?


Rodney

Recommended Posts

Hi

I would like to create a series of comm devices via a sequence

I have read this forum post

but it gets way too technical for me as I read through it

you say you can create the device but you cannot use in Channels

Basically I wish to create a comm device for each site (up to 20 as required) my project has (on the fly) so I can poll the data in separate threads continuously

I don't want to hard code via the quick Device Configuration Tool if i can avoid it

Each one would be an Ethernet port using modbusRTU just with a different IP address and name

Can it be done?

Regards

 

Rodney

 

 

 

 

Link to comment
Share on other sites

Hi

after reading and re-reading the original post I came up with this basic test sequence to try and create a device

Site_TCP = new(CCommEthernet)
Site_TCP.PortObject = "CS_TCP"
Site_TCP.ProtocolName = "ModbusRTU"
Site_TCP.address = "10.2.153.79"
Site_TCP.port = 8899
Site_TCP.timeout = 2000
Site_TCP.InitComm()
Channel.Add("temp","Site_TCP",10,"Read Input U16 (4)",12561,1,0,"","main")
 

I cannot get the channel to add as I cannot create the device (I used the same Channel.add syntax in another test file sequence and it worked)

obviously my syntax is incorrect - or this is way beyond my limited programming skills - feel free to tell me so!!

your guidance with the syntax most appreciated

Rodney

 

 

 

Link to comment
Share on other sites

First, dynamic ports and comm objects is script only.  You can't use channels with it at all.  It's really designed to be used within other objects that do all the polling and data handling.

Second, you should reread that other forum thread and specifically look at Steve's sample code, specifically the second to last one where the only mistake was that he included the Device. in his queries.   Once you fix his mistake and modify the script for your IP and port you should be able to get one device working.  Then you can look at how to support multiple devices.

 

Link to comment
Share on other sites

hmmm now I am confused

when you say you cannot use channels at all  - I was hoping to use a script to dynamically generate Channels (not via the user interface) -  I am a little lost

when you say "other objects"  what "objects" are these? (I was hoping they were channel objects - obviously not)

can you give me an example?

Re the second last post

I thought it was creating the device so you could then use Channels

by using the script how then would you access a "Channel"/ "object"

am I missing a fundamental point?

Rodney

 

 

 

Link to comment
Share on other sites

I have just had a re-read of the code you suggested and I think the penny has dropped!!

I need to create both a CCommEthernet AND CCommDevice

then use readholdings16() (or other as required) I read the "Channels" on the device directly

Am I on the right track?

 

 

 

 

Link to comment
Share on other sites

got it to work!!!

now a couple of bigger picture questions

If I use this method of creating a comm device does that mean I can never use any of the built in objects like channels, graphs etc - i will always have to script them?

I would have to set all my own timings / offset etc etc?

Rodney

 

 

 

Link to comment
Share on other sites

You can use most all of the built in objects like graphs, alarms, etc, you just can't use channels for the actual acquisition the way you normally would.  Once you do the ReadHolding() you just need to decide where you want to store the results, and then you can access that data.  You can, technically, use Channels to store the results by using myChannel.addValue() to stuff your results into a particular channel, but it won't scale particularly well. 

Yes, you would have to setup the timing and the acquisition.

Link to comment
Share on other sites

Hi

As I said I got a single commdevice to work and update a variable - (commented out as I am not connected at the moment)

I tried a simple script to add a 2nd device but it appears not to gave worked as now the IP address for both is the same - see attached screenshot

Again your help appreciated

Rodney

 

 

comm_device_setup.PNG

Link to comment
Share on other sites

Leading on from your reply re cannot use channels for data acquisition

What about the set channel function

I have a named component for a switch and the parameter is set Channel

I use this line of code to update the channel so the correct Channel is toggled based on the site chosen

component.RelaySwitch1.strSetChannel = Sites[site_id[]] +"_Relay1"

it works under my present set up

If go down the road of creating my own comms device I won't have Channels

so how do I set the Channel in the switch parameter - use "forcecoil" somehow?

Rodney 

 

 

Link to comment
Share on other sites

First post:

The problem is that you created two devices but assigned them both to the same port.  You need two devices each with their own port.  Note that two devices with the same port is a valid setup: for example, if you have a multidrop situation and an Ethernet -> RS485 converter.

Second post:

this is trickier, but there are several ways to handle it.  You can still create a channel for outputs, using a Test D to A channel, then in the Channel Event have it call code to actually set the output.  But I generally prefer to keep all my acquisition and control for a particular device in the same thread, so what I'll do is have the UI change a variable (or channel), but then inside my acquisition loop, I'll look at that variable and see if its changed from the last output value.  If it has, then I make the output call.  If not, I move on.   I do this in the same loop that all my acquisition reads are in.  That way I don't get any conflicts.

Link to comment
Share on other sites

Re your reply for the 1st post 

I thought I was using a multidrop setup with Ethernet-> RS485 converters

I will have a converter at each site obviously with its own unique IP (I'm testing with 3 on my desk right now succesfully)

see the attachment - my current hard coded test setup

Site_TCP has 3 Ports

CB_Conn

CS_Conn

CW_Conn

I call each one each in its own thread - and they poll simultaneously - which is what I need 

this is what I am trying to replicate via the Sequence

one ethernet device  - Site_TCP

multiple ports - xx_Site - one for each site with its own unique IP

I thought my test sequence was doing this

I could set up a device for each site as you suggested but was looking for a more "elegant" solution

I think I may have the terminology wrong in my head... 

Rodney

 

Current_Comm_Setup.PNG

Link to comment
Share on other sites

If they have different IP addresses, then its not Multidrop.  Multidrop would be if you had an Ethernet - RS485 converter and then had 3 devices connected to the RS485 side of the converter.  Those three devices would have the same IP from DAQFactory's point of view because DAQFactory just sees the converter.  Then in Modbus, each individual device is addressed.  In these situations you can't poll simultaneously because the RS485 line is a bottleneck and only allows communications with one device at a time.

If however you have 3 devices in the field and each is connected to its own Ethernet - RS485 converter (or 232 converter, or just directly), where DAQFactory uses a different IP address to access the devices, then you are not multidrop.  Then you should create a different "device" within DAQFactory for each physical device, and each "device" should have its own "port" associated with it, where each "port" has its own different IP address.  Then you can poll the different IP addresses simultaneously.  What you did in the script I commented on is create two "devices" within DAQFactory, but both devices reference the same "port", and then you are changing the IP address of the "port".  You got the first part right, but each of the "devices" should have its own "port" and each "port" would have its IP address already setup.

If its not obvious, when I put "device" and "port" in quotes I mean a device or port within DAQFactory.  Usually these line up with their physical equivalent.

Link to comment
Share on other sites

Thank-you  - all makes sense now

FYI I am actually using Multidrop as each Site has an Ethernet -RS485 Converter (with its own unique IP address) and connected to each converter are several Modbus devices (each with their own unique Modbus device number)

This the reason why I would like to set up everything on the fly via a sequence - up to 20 sites with up to 10 Modbus devices at each site = 200 unique devices with maybe say up to 10 Channels on some devices - so the fewer things I need to hard code the better!!

Regards

Rodney

 

 

 

 

 

Link to comment
Share on other sites

Hi

Not sure if this reply belong here or under the Data Acquisition Forum

you said above that

" You can, technically, use Channels to store the results by using myChannel.addValue() to stuff your results into a particular channel, but it won't scale particularly well." 

what intrigues me is "it won't scale particularly well"

if I can get the sequence to generate all the channels I need (say 20 sites x 10 different equip per site x say average 10 channels per equip = 2000) by using execute - is that the scale issue you mention?

I was also thinking of using arrays to do it however I think the channels option would be easier as they give me persistence history and data logging etc (unless I can use these options with arrays?)

Regards

Rodney

 

 

Link to comment
Share on other sites

Let's start with the first post.  So you are multidrop.  You should probably create one device for each converter, not each connected 485 Modbus device.  The reason is that they are all talking the same protocol, and you probably should poll them all from a single thread since the 485 chain can't handle more than one communication frame at a time.

On to the second post.  Yes, you can use channels that way, and it will reduce some of the scaling issues.  You'll want a decent naming convention.  But one of the big advantages of using objects to hold common data is that you can create one screen that manipulates that data (display or control) and then change which item you are viewing/controlling with a simple assignment.  Yes, you can do this with Channels and using a lot of evaluate() and execute() functions, but it gets messy fast.

No, you can't do persist with an array, but typically if I'm doing a more advanced app that wants long term historical access, I'll store into a MySQL server so I can query the data in ways I wouldn't be able to do with Persist.  I also do all my data logging in script as well, especially if I'm going to a database.  

 

Link to comment
Share on other sites

Hi

looks like MY lack of DF terminology and understanding has confused us both

I have created 1 device for each converter not each Modbus device - so my current test bed has 3 ip converters

one has 2 modbus devices attached the 2nd 3 and the 3rd 1

your comment  "you probably should poll them all from a single thread since the 485 chain can't handle more than one communication frame at a time."  might change the way I intended to poll the devices

please confirm that in a while loop i CANNOT do this

while 1()

poll converter site1

do something

poll converter site2

do something

poll converter site3

do something

delay(1)

end while()

I was hoping each poll would be in its own thread so I was actually polling the 3 sites at the same time (eventually up to say 20 sites at the same time)

If I cannot do this it means I would have to change my thinking and poll each one in sequence 

re your paragraph 2 above - this was the 1st thing I did and I have it working - the user just chooses a site from a drop down box and all displayed / updated data then relates to that site

it does use evaluate a lot but my I set up my naming convention based on your excellent article on multi boilers - it's the foundation building block for the whole project

re your last comment on databases  - i will start with simple csv files to get my graphs etc (but using script to updates the data values) with the intention to move to an SQL at a later stage once i can actually get this project working..... 

 

 

 

 

Link to comment
Share on other sites

Doing:

while(1)
   poll converter site 1
   ...
   poll converter site 2
   ...
   poll converter site 3
   ...
endwhile

Won't poll them simultaneously because you have a single thread.  Multiple threads would mean three different sequences:

Sequence 1:

while(1)
   poll converter site 1
   ...
endwhile
 

Sequence 2:

while(1)
   poll converter site 2
   ...
endwhile

etc.

There is a way to start threads in script rather than creating sequences, but now we are getting pretty advanced...

What I meant was that you can't poll two Modbus devices on a single 485 chain attached to a single converter simultaneously, because 485 doesn't support it.  You can poll the three converters simultaneously because that connection is Ethernet and Ethernet (and DAQFactory) does support simultaneous communication to different Ethernet locations.  So, right now, you can create 3 threads to poll your three sites simultaneously.  You cannot create 6 threads to poll the 6 end Modbus devices simultaneously.

Link to comment
Share on other sites

Thanks for the reply - understood

I now have another issue with Dynamically creating Channels

I have been semi successful in doing this

to make sure I was generating the correct syntax I concatenated a string as I went - see Channel_Test1 in the screenshot of part of my sequence and then displayed it

- see the command / alert window

Once I was happy I then did execute Channel.add with the same variables (and removing the characters not required) to create the Channels required - all worked

If I display Channel.CB_Temp.DeviceNumber - 10 - its correct

same with Channel.CB_Temp.Channel - 12561 - its correct

if I display Channel.CB_Temp.strIOType - A to D - which is incorrect should be "read holding S16 (4)"

if I display Channel.CB_Temp.strDevice - Test - again incorrect - should be CB_TCP_Port

What have I done wrong? 

The data returned I think is all test sine data not the actual data values I was receiving previously

Rodney

 

Dynamic_Channels.PNG

Link to comment
Share on other sites

1) execute() isn't needed for what you are doing.  The function itself can take strings, so you can build it up like you did.  In fact, what you did is called execute() on whatever channel.add() returns, which in this case is NULL, so you are calling execute() with nothing, so that part does nothing.  You can just drop the execute, or do execute on channel_test1, but really you don't need to build up channel_test1.

2) for reading holding, you want (3), not (4).  Holding registers use function 3, not function 4.

3) not sure why you end up with a test device.  It works fine for me.  Does it do it for all the channels you add?

 

Link to comment
Share on other sites

After many hours of troubleshooting this Channel.Add issue I finally worked it out.....

As I am generating the Comms devices via a sequence they are object based and you specifically said in your post of 21 Sep  

" You can use most all of the built in objects like graphs, alarms, etc, you just can't use channels for the actual acquisition the way you normally would "

DoH!!!

(it was the the device parameter in the Channel.add function that caused the problem - it wasn't recognised)

What confused me was in a later post you said you can use channel.addValue() - I just saw the word channel and off I went...... - my fault!!

I still need the nested loops I developed to generate the Channels -  I just need to use them in a different way for the data acquisition sequences

 

 

Link to comment
Share on other sites

First question

in regards to the 2 types of Modbus Addressing that DAQ can use - by using my sequence generating comms device I have come across an issue 

I started a thread

based on your reply I got it to work

The issue I think I have now is the my comm device is an object not a regular comm device and the the fix you gave me does not appear to work 

Am I on the right track? 

if so what do I need to do to change the Modbus addressing so I can read my register 36883

Second Question

This relates to sequences and  multiple threads per you replies above

If called the same sequence a number of times would it run simultaneously each in its own thread every time I called it?

My idea is to pass different site parameters to it each time it was called and have the sites polled simultaneously as you explained above

Rodney

 

 

 

Link to comment
Share on other sites

First question: 

Even though you are creating the comm device as an object, its still using the same protocol code in DAQFactory, so reading a register over 50,000 will still put it in 0 index mode.

Second question:

You can't do that.  For one, its pretty hard to pass parameters to a thread, but more importantly, once a sequence is running, trying to start it again will do nothing.  You can only have one instance of a sequence running at once.

There are two solutions to this:

1) if I only have to fire up a few copies of the sequence (say under 20?) Then what I'll do is create a sequence function (basically a sequence that takes parameters), and then create a whole bunch of other sequences that call that sequence with the different parameters.  I'd only start those other sequences.  For example:

Sequence PollDevice:

function pollDevice(string name, id, deviceOb)
    // .. read from a particular id/deviceOb
 

Sequence PollSite1:

pollDevice("remote A", 1, deviceObA)

Sequence PollSite2:

pollDevice("remote B", 2, deviceObB)

etc.

Then only run PollSite1, PollSite2, etc.  Never run PollDevice directly.  This works fine except of course you end up with a lot of sequences.

2) dynamically create threads.  This, as I mentioned is a bit more advanced.  Not hard, its just you have to keep track of more (namely the threads).  If you lose track of them, you can create problems.  Knowing your programming level, I'd suggest sticking with #1.  With sequences, its pretty obvious what is running and not, and DAQFactory will help with it.

 

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.