Menu

Speed problem?

Help
2015-06-23
2015-06-23
  • michael hompus

    michael hompus - 2015-06-23

    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

     
    • Fabio Luis Girardi

      Hi Michael!

      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:

      implementation
      
      uses Tag;
      
      ...
      ...
      
      procedure TForm1.Button1Click(Sender: TObject);
      var
        cmd:TArrayOfDouble;
      begin
        SetLength(cmd, 2);
        try
          cmd[0]:=1;
          cmd[1]:=1;
          PLCBlock1.Write(cmd, //values to write
                          2,   //lenght of cmd
                          0);  //address offset, PLCMemAddress + thisvalue
        finally
          SetLength(cmd, 0);
        end;
      end; 
      

      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
  • michael hompus

    michael hompus - 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

     
    • Fabio Luis Girardi

      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.

      procedure TForm1.Button1Click(Sender:TObject);
      var
        retries:integer;
      begin
        retries := 0;
        repeat
          YourTag.Write(...);
          Inc(retries);
          if retries = 3 then begin
            if CustomMessageDlg('Something go wrong when writing, try again?', mtConfirmation, mbYesNo, 0) = mrYes then
              retries := 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.

       
  • michael hompus

    michael hompus - 2015-06-23

    OK, got it.
    I am using Lazarus at the moment, so I'll install that package.
    Michael

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.