g_dickinson

Initializing Knob component

Recommended Posts

Is there a mechanism to set the initial value of a knob component?

I notice that when I start DaqFactory, my knob component goes to it's minimum value.

I'm using the knob to set a 16bit signed value using Modbus ASCII protocol.

Is there a way to read the 16bit value from the PLC on start up of DaqFactory and get the knob the match the current value of the 16bit value?

I've configured the channel affected by the knob component as "Read Holding S16 (3)". Is there some more appropriate way to set up the channel?

Share this post


Link to post
Share on other sites

The knob initializes with whatever variable / channel value is set. If you haven't read the channel yet, it will init to 0. On Modbus RTU at least, you can do Read Holding and use it both as an input and output, but I'm not sure about ASCII. You can initialize it manually in an autostart sequence by doing something like:

mychannel.addvalue(20)

which puts the value of 20 into mychannel, which if the knob is referencing mychannel, will set it to 20.

Share this post


Link to post
Share on other sites

I'm using a Triangle Research MD100-1616+ PLC. I find that Modbus ASCII is the most reliable protocol.

I have defined the I/O type as "Set Register S16 (16)" for channel "DM_3". This channel behaves as if it is write only channel.

I setup a second channel, DM_3_RD as "Read Holding S16 (3)". This channel behaves as if it is read-only.

I set up the following sequence that runs with the "5-Acquisition" priority with "Auto_Start" checked:

read(DM_3_RD)

DM_3 - DM_3_RD[0]

If I associate a "Spin Button" with channel DM_3, everthing works as I expect. If I click the "increment" button, the channel DM_3 is incremented by the internal value for the "Spin Button".

If I associate a "Knob Component" with channel DM_3. I find that channel DM_3 is reset to "0" when DAQFactory runs my ".ctl" file. If I look in the DM_3 channel hsitory (table) I see that the channel was set to the value of the register in my PLC by the sequence run at startup, and the DM_3[0] entry is "O". The register in the PLC is now also, 0.

If I enter the following command in the command line:

read(dm_3)

The value returned is 0. This makes reasonable sense, as DM_3 is a read_only channel.

I suspect that the "Knob component" is attempting to "Read" a write-only channel. How do I prevent this behavior?

Using C++ terminology, is there a default initiator for the "Knob Component"? Can I override this behavior? I would like this component to NOT attempt to read from a read-only channel and/or to not force a "0" into the channel history.

Is it possible to get a "Knob component" to behave the same as the "Spin button" on startup?

I have attempted to add the following code to the "OnLoad" event associated with the "Knob Component":

DM_3 = DM_3_RD[0]

BUT, I find no evidence that this code has run and no evidence that this code resulted in an entry in the DM_3 channel history.

If I attempt to use the the "knob component" to control the DM_3_RD channel (Read Holding S16), a "0" is written to this channel by the "knob component". So I'm back to my same set of questions:

Is it possible to get a "Knob component" to behave the same as the "Spin button" on startup?

Is there any way to initialize the "Knob component" without it first writting "0" to the channel?

Thanks.

Share this post


Link to post
Share on other sites

I guess ASCII doesn't have the bidirectional i/o types like RTU and TCP.

>> Is it possible to get a "Knob component" to behave the same as the "Spin button" on startup?

No.

>> Is there any way to initialize the "Knob component" without it first writting "0" to the channel?

Yes, provided the knob isn't on your initial screen you should be able to simply change the value of the channel it is referencing. This is, presumably, your output channel, so do:

read(DM_3_RD)

DM_3.AddValue(DM_3_RD[0])

This will read the input and set the history of DM_3 to that value, thus initializing it. Using AddValue() prevents DF from sending the command to the device. It just inserts it into the history.

Share this post


Link to post
Share on other sites

Thanks for your reply,

Modbus ASCII, does have bidirectional access. If I change the I/O type type to "Read Holding S16", then I get another set of problems:

If I set the channel Timing to "0", then the knob cannot rotate.

If I set the channel Timing to "1", then when the knob is moved to a new position, it will oscillate back and

forth between the previous position and the new position. This osscilation will continue until I can hold the

knob in a new position for longer than the channel timing period, in this case 1 to 2 seconds.

So you can see why I abandoned using the bidirectional I/O types...

Back to my Initialization problem:

I changed the sequent tat is to Auto-start to have the following code:

read(DM_3_RD)

DM_3.AddValue(999) // marker for debug

DM_3.AddValue(DM_3_RD[0])

Page_0 now has NO componets. The knob component has been moved to Page_1. The knob component was set up with a range of 0 to 1023.

When I start DAQFactory and open my ".ctl" file this is the contents of the DM_3 (channel associated with knob component):

Row: Time: Value:

0 ...m39.760 509 <- this is value read from my PLC

1 ...m39.845 999 <- this is my marker

After I goto to Page_1 (has knob component), but before touching the knob, this is what I see in the DM_3

channel table:

Row: Time: Value:

0 ...m55.834 0 <- this is the value that your knob component wrote to my PLC

1 ...m39.760 509 <- this is value read from my PLC

2 ...m39.845 999 <- this is my marker

I see no evidence that the "knob component" is using the channel history for it's initialization. I changed the range on the knob to 10.5 to 1023 and found that the knob initialized to a value of 10.5. It is not possible to get a value of "10.5" from an integer register, so I conclude that the knob component made no attempt to access a register in my PLC, but rather defaulted to the minimum value of the component.

OK, so here's the questions, again:

Is it possible to initialize the Knob component to a starting value other than it's minimum value when working with a "write-only" channel?

Is it possible to associate the knob component with a virtual channel (bidirectional) and then redirect the channel writes to a "real" (physical) channel and if the component request a "read" to provide this information from another channel or data source?

Share this post


Link to post
Share on other sites

Just for your amusement:

The "Slider Component" behaves differently then the "Knob Component".

The "Slider component" DOES use the channel history for initialization when the Set Channel is write only.

The "Knob Component" uses it's minimum value for initialization when the Set Channel is write only.

Thanks for your kind attention.

Share this post


Link to post
Share on other sites

I'm afraid I can't tell you why it reacts that way. In general I shy away from using the knob for slow devices. However, using a variable as an intermediary is a good way to make the knob work the way you want. I wouldn't use a v channel, just use a global variable. The only thing is that you would need a little sequence that checked that variable and when it changed, set the actual output. It would be a pretty simple sequence:

global knobval = 1000
while(1)
   if (knobval != DM_3[0])
	  DM_3 = knobval
   endif
   delay(0.1)
endwhile

You'll need to preset DM_3 to some value so the if() can evaluate the first time.

Share this post


Link to post
Share on other sites

Thanks guru

You suggestion of hitching the knob component to a variable solved alot of problems.

I now can:

1. Initialize the knob component, consistently

2. Get it to work with integer values (my physical channel is a int16).

I used the global variable "knobval" as the Set Channel for a knob component.

DM_20 is a Modbus U16 Holding Register. This register can is R/W.

This code works well with the "Knob Component". The FirstTime flag is used to detect the first time that the variable, knobval, is changed by the "Knob Component". As, I've figured out, the knob component's initial value is not determined by the initial value of the Set Channel (knobval in this case) but by the component.minRange variable.

I set the channel timing to 0 so anything that shows up in the History is a result of the following sequence:

global knobval
global FirstTime = 1				// haven't figured out correct syntax
											//   for a local variable, yet.

read(DM_20)						 // Get Physical channel value
knobval = DM_20[0]			  //   and try to get knob to match

while(1)

   if (knobval != DM_20[0])		 // knob has been moved
	  if (FirstTime)					   // If is the first time it's moved
		 knobval = DM_20[0]		 //   then force the knob to match the channel
		 FirstTime = 0				   //   only a virgin once
	  else
		 knobval = floor(knobval)   //   Write the integer part 
		 DM_20 = knobval			 //	  to the physical channel
		 read(DM_20)				   //	  and update channel history
	  endif
   endif

   delay(0.2)							// polling rate

endwhile

Share this post


Link to post
Share on other sites

I am developing a HMI interface where there will be two or three HMIs talking to the PLC. The problem I have is I can't seem to fully initialise the knob components. If the PLC is running the line and the HMI is powered up I need it to pick up the comveyor speeds and initialise the speed adjustment knobs without affecting the PLC. When I fire up the HMI it does seem to initialse OK when looking at the variables in the watch window. However when I switch to the page with the knobs on it resets to zero and writes it to the PLC. 

Can you advise how I can solve this please?

I've included a screen shot of the initial page and the variables in the watch window and everything is stable. I've then also included a screen shot of what happens when I switch to the page with the knobs on.

knob_initialisation.zip

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now