I have 4 Stepper-motor drivers on ModBus in an XYZ table. The X-axis is driven by two motors (and spindles), so they MUST start and stop at the "same" time. The start command is either writing a value to a 16bit register or setting a bit in the bit-area of the drives. I am using a TPLCTagNumber for the former and a TPLCBlockElement to access the latter. I suppose that writing to the two tags (motor 1 and 2) by
TagStartMotor1.Value:=1;TagStartMotor1.Value:=1
is not ideal because the updates are done at when the scheduler has time for it. (depending on UpdateTime and total number of tags etc. of course)
How can I force an immediate writing of both variables, so they arrive at the motor drives (almost) at the same time, without being interrupted by the regular update mechanism?
Another issue: There is a physical limit to the number of tags that can be updated within a certain time, so giving each tag a short UpdateTime value must leads to timing conflicts.... Is there a way of finding out whether I am "overloading" the communication or getting close?
BTW I am using PascalScada on Windows 7.
Michael
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have 4 Stepper-motor drivers on ModBus in an XYZ table. The X-axis is driven by two motors (and spindles), so they MUST start and stop at the "same" time. The start command is either writing a value to a 16bit register or setting a bit in the bit-area of the drives. I am using a TPLCTagNumber for the former and a TPLCBlockElement to access the latter. I suppose that writing to the two tags (motor 1 and 2) by
TagStartMotor1.Value:=1;TagStartMotor1.Value:=1
is not ideal because the updates are done at when the scheduler has time for it. (depending on UpdateTime and total number of tags etc. of course)
How can I force an immediate writing of both variables, so they arrive at the motor drives (almost) at the same time, without being interrupted by the regular update mechanism?
I suppose that are you using modbus RTU. With it, you can only reduce the effect of the scanner, doing:
TagStartMotor1.Write(1);
TagStartMotor2.Write(1);
The Write procedure is synchronous, it stops the scanner, do your task (read or write) and starts the scanner again. It will freeze your application for a short time (milliseconds) until the I/O operation finishes, since the entire I/O operation will be done by the main thread, not by the scanner thread. This I/O latency is more visible when using serial, and less visible using ethernet.
Using modbus you can only reduce this effect, since modbus don't support multiple I/O requests on a single packet, like in Siemens ISOTCP. Using modbus, it will make the packet, send it, wait the response from the slave, to only after this sequence of events, release the driver to another read/write, or on your case, write the TagStartMotor2.
If TagStartMotor1 and TagStartMotor2 maps two subsequent register address (by example address 10 and 11, 1 and 2, ...) you can improve this task using a TPLCBlock:
On this case, PLCMemAddress of PLCBlock1 must point to the first address.
Another issue: There is a physical limit to the number of tags that can be updated within a certain time, so giving each tag a short UpdateTime value must leads to timing conflicts.... Is there a way of finding out whether I am "overloading" the communication or getting close?
No, currently, this is the unique way. You can watch the property AvgUpdateRate of your tags to see if it is updated as expected or not. I use prime numbers to avoid conflicts of this type.
Last edit: Fabio Luis Girardi 2015-06-23
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks Fabio.
I like the example with the array. I had tried something like that with an ordinary (non dynamic) array. Yours is more elegant.
I am still 'struggling' with the procedures.... different tags (or rather tag variants) seem to use different write (and read) procedures.
Is there a simple way to check if a write has been completed? I'd expect the scanner to finish its current job before a synchronous write can take place. I need to make sure the setpoints have arrived at the drives before issuing the start command. Of course I could read back the value and compare until......
Checking AvgUpdateRate is a good suggestion, I had not found that one yet.
Michael
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Is there a simple way to check if a write has been completed? I'd expect the scanner to finish its current job before a synchronous write can take place. I need to make sure the setpoints have arrived at the drives before issuing the start command. Of course I could read back the value and compare until......
Yes, I did this example on wiki, but spammers phished it and I need to shutdown the wiki.
procedureTForm1.Button1Click(Sender:TObject);varretries:integer;beginretries:=0;repeatYourTag.Write(...);Inc(retries);ifretries=3thenbeginifCustomMessageDlg('Something go wrong when writing, try again?',mtConfirmation,mbYesNo,0)=mrYesthenretries:=0;end;until(YourTag.LastSyncWriteStatus=ioOk)or(retries=3);end;
Checking AvgUpdateRate is a good suggestion, I had not found that one yet.
I don't remember if you are using lazarus or Delphi. But on Lazarus, install the package RunTimeTypeInfoControls. This package has a component class called TTIPropertyGrid. Use it together with a TTimer to refresh it. It's very useful to debug runtime components.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Fabio,
I have 4 Stepper-motor drivers on ModBus in an XYZ table. The X-axis is driven by two motors (and spindles), so they MUST start and stop at the "same" time. The start command is either writing a value to a 16bit register or setting a bit in the bit-area of the drives. I am using a TPLCTagNumber for the former and a TPLCBlockElement to access the latter. I suppose that writing to the two tags (motor 1 and 2) by
TagStartMotor1.Value:=1;TagStartMotor1.Value:=1
is not ideal because the updates are done at when the scheduler has time for it. (depending on UpdateTime and total number of tags etc. of course)
How can I force an immediate writing of both variables, so they arrive at the motor drives (almost) at the same time, without being interrupted by the regular update mechanism?
Another issue: There is a physical limit to the number of tags that can be updated within a certain time, so giving each tag a short UpdateTime value must leads to timing conflicts.... Is there a way of finding out whether I am "overloading" the communication or getting close?
BTW I am using PascalScada on Windows 7.
Michael
Hi Michael!
I suppose that are you using modbus RTU. With it, you can only reduce the effect of the scanner, doing:
TagStartMotor1.Write(1);
TagStartMotor2.Write(1);
The Write procedure is synchronous, it stops the scanner, do your task (read or write) and starts the scanner again. It will freeze your application for a short time (milliseconds) until the I/O operation finishes, since the entire I/O operation will be done by the main thread, not by the scanner thread. This I/O latency is more visible when using serial, and less visible using ethernet.
Using modbus you can only reduce this effect, since modbus don't support multiple I/O requests on a single packet, like in Siemens ISOTCP. Using modbus, it will make the packet, send it, wait the response from the slave, to only after this sequence of events, release the driver to another read/write, or on your case, write the TagStartMotor2.
If TagStartMotor1 and TagStartMotor2 maps two subsequent register address (by example address 10 and 11, 1 and 2, ...) you can improve this task using a TPLCBlock:
On this case, PLCMemAddress of PLCBlock1 must point to the first address.
No, currently, this is the unique way. You can watch the property AvgUpdateRate of your tags to see if it is updated as expected or not. I use prime numbers to avoid conflicts of this type.
Last edit: Fabio Luis Girardi 2015-06-23
Thanks Fabio.
I like the example with the array. I had tried something like that with an ordinary (non dynamic) array. Yours is more elegant.
I am still 'struggling' with the procedures.... different tags (or rather tag variants) seem to use different write (and read) procedures.
Is there a simple way to check if a write has been completed? I'd expect the scanner to finish its current job before a synchronous write can take place. I need to make sure the setpoints have arrived at the drives before issuing the start command. Of course I could read back the value and compare until......
Checking AvgUpdateRate is a good suggestion, I had not found that one yet.
Michael
Yes, I did this example on wiki, but spammers phished it and I need to shutdown the wiki.
I don't remember if you are using lazarus or Delphi. But on Lazarus, install the package RunTimeTypeInfoControls. This package has a component class called TTIPropertyGrid. Use it together with a TTimer to refresh it. It's very useful to debug runtime components.
OK, got it.
I am using Lazarus at the moment, so I'll install that package.
Michael