Editing Optimizing SimpleMotion V2 performance

Jump to: navigation, search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

This page supports semantic in-text annotations (e.g. "[[Is specified as::World Heritage Site]]") to build structured and queryable content provided by Semantic MediaWiki. For a comprehensive description on how to use annotations or the #ask parser function, please have a look at the getting started, in-text annotation, or inline queries help page.

Latest revision Your text
Line 14: Line 14:
 
===Optimizing code===
 
===Optimizing code===
 
The easiest way to use SMV2 library is to use ''smSetParameter'' and ''smRead1Parameter'' commands. However these commands are not optimal as they set and read only one parameter at the time and all latencies are added to this single call.
 
The easiest way to use SMV2 library is to use ''smSetParameter'' and ''smRead1Parameter'' commands. However these commands are not optimal as they set and read only one parameter at the time and all latencies are added to this single call.
===Queued calls===
+
====Queued calls====
 
The more optimal way is to use '''queued''' SM commands. Queued command is a list of commands that are transferred to a slave in single data transfer, executed as a batch in the slave and finally all return data is returned as list. In this case bus latencies occur only once per multiple commands.
 
The more optimal way is to use '''queued''' SM commands. Queued command is a list of commands that are transferred to a slave in single data transfer, executed as a batch in the slave and finally all return data is returned as list. In this case bus latencies occur only once per multiple commands.
  
 
Instead of doing this...
 
Instead of doing this...
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
smSetParameter( busHandle, deviceAddress, paramAddr1, paramVal1 );
+
smSetParameter( handle, deviceAddress, paramId1, paramVal1 );
smSetParameter( busHandle, deviceAddress, paramAddr2, paramVal1 );
+
smSetParameter( handle, deviceAddress, paramId2, paramVal1 );
smSetParameter( busHandle, deviceAddress, paramAddr3, paramVal1 );
+
smSetParameter( handle, deviceAddress, paramId3, paramVal1 );
smSetParameter( busHandle, deviceAddress, paramAddr4, paramVal1 );
+
smSetParameter( handle, deviceAddress, paramId4, paramVal1 );
 
</syntaxhighlight>
 
</syntaxhighlight>
 
...one may do this:
 
...one may do this:
Line 28: Line 28:
 
smint32 nul;
 
smint32 nul;
 
//append commands to queue
 
//append commands to queue
smAppendSetParamCommandToQueue( busHandle, paramAddr1, paramVal1 );
+
smAppendSetParamCommandToQueue( handle, paramId1, paramVal1 );
smAppendSetParamCommandToQueue( busHandle, paramAddr2, paramVal2 );
+
smAppendSetParamCommandToQueue( handle, paramId2, paramVal2 );
smAppendSetParamCommandToQueue( busHandle, paramAddr3, paramVal3 );
+
smAppendSetParamCommandToQueue( handle, paramId3, paramVal3 );
smAppendSetParamCommandToQueue( busHandle, paramAddr4, paramVal4 );
+
smAppendSetParamCommandToQueue( handle, paramId4, paramVal4 );
  
 
//execute commands over SM bus
 
//execute commands over SM bus
Line 40: Line 40:
 
before appending new commands. So each smAppendSetParamCommandToQueue will need  
 
before appending new commands. So each smAppendSetParamCommandToQueue will need  
 
one smGetQueuedSetParamReturnValue after smExecuteCommandQueue.*/
 
one smGetQueuedSetParamReturnValue after smExecuteCommandQueue.*/
smGetQueuedSetParamReturnValue(  busHandle, &nul );
+
smGetQueuedSetParamReturnValue(  handle, &nul );
smGetQueuedSetParamReturnValue(  busHandle, &nul );
+
smGetQueuedSetParamReturnValue(  handle, &nul );
smGetQueuedSetParamReturnValue(  busHandle, &nul );
+
smGetQueuedSetParamReturnValue(  handle, &nul );
smGetQueuedSetParamReturnValue(  busHandle, &nul );
+
smGetQueuedSetParamReturnValue(  handle, &nul );
 
+
//TODO add some SM error checking in appropriate places
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
In the above example, the ''smExecuteCommandQueue'' is the only line where RS485 is being used thus generating only one write-read latency instead. ''smAppendSetParamCommandToQueue'' and ''smGetQueuedSetParamReturnValue'' transfer data only inside SMV2 library buffers and are fast calls. The optimized code does only one bus transfer cycle instead of four.
+
In the above example, the ''smExecuteCommandQueue'' is the only line where RS485 is being used thus generating only one write-read latency. ''smAppendSetParamCommandToQueue'' and ''smGetQueuedSetParamReturnValue'' transfer data only inside SMV2 library buffers and are fast calls.
  
====Queued size limit====
+
=====Queued size limit=====
 
One SMV2 command or return data packet can hold up to 120 bytes of payload data. This means that one should not add too many commands to the queue to avoid exceeding the 120 byte limit in outbound or inbound direction.
 
One SMV2 command or return data packet can hold up to 120 bytes of payload data. This means that one should not add too many commands to the queue to avoid exceeding the 120 byte limit in outbound or inbound direction.
  
 
Single smAppendSetParamCommandToQueue commands consumes maximum of 6 bytes in outbound data and smGetQueuedSetParamReturnValue maximum of 4 bytes. So one can safely queue 20 set parameter commands in the one transfer.
 
Single smAppendSetParamCommandToQueue commands consumes maximum of 6 bytes in outbound data and smGetQueuedSetParamReturnValue maximum of 4 bytes. So one can safely queue 20 set parameter commands in the one transfer.
 
+
====Low level queued commands====
===Low level queued commands===
+
{{info|This is work in progress chapter, don't use}}
 
This section shall describe how to further optimize communication by using lower level queued commands instead of smAppendSetParamCommandToQueue and smGetQueuedSetParamReturnValue which do some dummy assumptions (such as all parameters are written as 30 bit values and every time parameter address is set even if it's not changed from the previous set parameter command). Also reading variables while writing one is possible without separate command which reduces the amount of SM commands needed.
 
This section shall describe how to further optimize communication by using lower level queued commands instead of smAppendSetParamCommandToQueue and smGetQueuedSetParamReturnValue which do some dummy assumptions (such as all parameters are written as 30 bit values and every time parameter address is set even if it's not changed from the previous set parameter command). Also reading variables while writing one is possible without separate command which reduces the amount of SM commands needed.
====Writing and reading multiple values at one cycle====
+
;Writing and reading multiple values at one cycle
 
Following example will:
 
Following example will:
*Initialize read-out parameter size to 24 bits. All consequent commands will have return data length of 24 bits until changed next time.
+
*Initialize read-out parameter address so that all further SM commands will return the desired parameter as return value
*Use variable parameter bit lengths to reduce amount of data transferred. For example sending 24 bit commands is good for values such as torque command or parameter values and 32 bits for position commands when travel length is large.
+
*Use custom parameter lengths to reduce amount of data transferred
  
 
Initialization code where we specify readout variable length.  
 
Initialization code where we specify readout variable length.  
Line 66: Line 64:
 
/*setting return data lenght to 24 bits (22 bits maximum returned integer value  
 
/*setting return data lenght to 24 bits (22 bits maximum returned integer value  
 
as 2 bits are used by SM protocol). 16 bit data will fit in return value without clipping. */
 
as 2 bits are used by SM protocol). 16 bit data will fit in return value without clipping. */
smSetParameter( busHandle, deviceAddress, SMP_RETURN_PARAM_LEN, SMPRET_24B);
+
smSetParameter( handle, deviceAddress,SMP_RETURN_PARAM_LEN, SMPRET_24B);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 119: Line 117:
 
     smExecuteCommandQueue( busHandle, deviceAddress );
 
     smExecuteCommandQueue( busHandle, deviceAddress );
  
     /*read value commands (one per each append command). Size of inbound payload depends on  
+
     //read value commands (one per each append command). Size of inbound payload depends on how large TODOTODO
    what was set to SMP_RETURN_PARAM_LEN at initialization */
+
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
Line 137: Line 134:
 
     smGetQueuedSMCommandReturnValue( busHandle,&readout2 );
 
     smGetQueuedSMCommandReturnValue( busHandle,&readout2 );
 
     smGetQueuedSMCommandReturnValue( busHandle,&readout3 );
 
     smGetQueuedSMCommandReturnValue( busHandle,&readout3 );
 
    //TODO add some SM error checking in appropriate places
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 
+
;Writing multiple and reading single value at one cycle
Below an alternative code that writes one variable (absolute setpoint) and read three variables (torque, position and velocity feedbacks). This code is present in live demo in [https://github.com/GraniteDevices/SMV2Commander SMV2Commander example].
+
<syntaxhighlight lang="c">
+
 
+
    //VALUES DEFINED
+
    int paramAddr1=SMP_ABSOLUTE_SETPOINT;
+
    int paramValue1=0;//your setpoint value
+
    int readOutParamAddr1=SMP_ACTUAL_TORQUE;
+
    int readOutParamAddr2=SMP_ACTUAL_POSITION_FB;
+
    int readOutParamAddr3=SMP_ACTUAL_VELOCITY_FB;
+
    smint32 nul, readout1, readout2, readout3;
+
 
+
    //WRITING PARAMETERS
+
    //set an parameter number where next values are written. This line consumes 2 bytes of outbound payload
+
    smAppendSMCommandToQueue( busHandle, SMPCMD_SETPARAMADDR, paramAddr1 );
+
 
+
    //write the parameter value to previously set parameter address. SMPCMD_24B consumes 3 bytes of outbound payload
+
    smAppendSMCommandToQueue( busHandle, SMPCMD_24B, paramValue1);
+
 
+
    //READING PARAMETERS
+
    //set parameter parameter number which will be returned from each command executed after this
+
    smAppendSMCommandToQueue( busHandle, SMPCMD_SETPARAMADDR, SMP_RETURN_PARAM_ADDR ); //consumes 2 bytes
+
    /*write new values to parameter SMP_RETURN_PARAM_ADDR. after execution these commands return the parameter values
+
    defined by readOutParamAddrN*/
+
    smAppendSMCommandToQueue( busHandle, SMPCMD_24B, readOutParamAddr1 ); //consumes 3 bytes
+
    smAppendSMCommandToQueue( busHandle, SMPCMD_24B, readOutParamAddr2 ); //consumes 3 bytes
+
    smAppendSMCommandToQueue( busHandle, SMPCMD_24B, readOutParamAddr3 ); //consumes 3 bytes
+
 
+
    //execute commands over SM bus
+
    smExecuteCommandQueue( busHandle, deviceAddress );
+
 
+
    /*read value commands (one per each append command). Size of inbound payload depends on
+
    what was set to SMP_RETURN_PARAM_LEN at initialization */
+
    smGetQueuedSMCommandReturnValue( busHandle,&nul );
+
    smGetQueuedSMCommandReturnValue( busHandle,&nul );
+
 
+
    smGetQueuedSMCommandReturnValue( busHandle,&nul );
+
 
+
    /*the next readouts reflect to the last three commands appended before smExecuteCommandQueue
+
    and here we get the readout values*/
+
 
+
    smGetQueuedSMCommandReturnValue( busHandle,&readout1 );
+
    smGetQueuedSMCommandReturnValue( busHandle,&readout2 );
+
    smGetQueuedSMCommandReturnValue( busHandle,&readout3 );
+
 
+
    //TODO add some SM error checking in appropriate places
+
</syntaxhighlight>
+
====Writing multiple and reading single value at one cycle====
+
 
If we need to read only one variable, we don't need to change readout parameter address during cycle and further improve performance. In this case we set it at initialization and then all consequent commands will return the desired return value.
 
If we need to read only one variable, we don't need to change readout parameter address during cycle and further improve performance. In this case we set it at initialization and then all consequent commands will return the desired return value.
 
Initialization:
 
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
 
     /* Variables:
 
     /* Variables:
     -readOutParamAddr1 will define the parameter number to be read out into readout1
+
     -readOutParamAddr1 will define the parameter numbers to read out into readout1
 
     */
 
     */
     smint32 nul, readOutParamAddr1=SMP_ACTUAL_POSITION_FB;
+
     smint32 nul, readOutParamAddr1==SMP_ACTUAL_POSITION_FB;
  
 
     /*setting return data lenght to 24 bits (22 bits maximum returned integer value
 
     /*setting return data lenght to 24 bits (22 bits maximum returned integer value
Line 216: Line 162:
 
     smGetQueuedSMCommandReturnValue( busHandle, &nul );
 
     smGetQueuedSMCommandReturnValue( busHandle, &nul );
 
     smGetQueuedSMCommandReturnValue( busHandle, &nul );
 
     smGetQueuedSMCommandReturnValue( busHandle, &nul );
 
    //TODO add some SM error checking in appropriate places
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Frequently called function with writing 3 variables and reading one in one bus transfer:
+
Now the same high speed function with writing 3 variables and reading one.
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
 
     /* Variables:
 
     /* Variables:
Line 252: Line 196:
 
     //write the parameter value to previously set parameter address. SMPCMD_32B consumes 4 bytes of outbound payload
 
     //write the parameter value to previously set parameter address. SMPCMD_32B consumes 4 bytes of outbound payload
 
     smAppendSMCommandToQueue( busHandle, SMPCMD_32B, paramValue3);
 
     smAppendSMCommandToQueue( busHandle, SMPCMD_32B, paramValue3);
 
    //notice that we don't need to change readout parameter addresses here as it we have only one variable to read out
 
  
 
     //execute commands over SM bus
 
     //execute commands over SM bus
 
     smExecuteCommandQueue( busHandle, deviceAddress );
 
     smExecuteCommandQueue( busHandle, deviceAddress );
  
     /*read value commands (one per each append command before execute). Size of inbound payload depends on  
+
     //notice that we don't need to change readout parameter addresses here as it we have only one variable to read out
    what was set to SMP_RETURN_PARAM_LEN at initialization. In this case 3 bytes per return value (total 6x3). */
+
 
 +
    //read value commands (one per each append command). Size of inbound payload depends on how large TODOTODO
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
Line 266: Line 209:
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&nul );
 
     smGetQueuedSMCommandReturnValue( busHandle,&readout1 ); //we could get the readout1 from any of the above lines as well
 
     smGetQueuedSMCommandReturnValue( busHandle,&readout1 ); //we could get the readout1 from any of the above lines as well
 
    //TODO add some SM error checking in appropriate places
 
 
</syntaxhighlight>
 
</syntaxhighlight>
==See also==
 
*[[Changing SimpleMotion baud rate]]
 
[[Category:Development]]
 
[[Category:SimpleMotion]]
 

Please note that all contributions to Granite Devices Knowledge Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see Granite Devices Knowledge Wiki:Copyrights for details). Do not submit copyrighted work without permission!

Select categories:

To edit this page, please answer the question that appears below (more info):

Cancel | Editing help (opens in new window)