Editing Optimizing SimpleMotion V2 performance
Your changes will be displayed to readers once an authorized user accepts them. (help) |
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.
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( | + | smSetParameter( handle, deviceAddress, paramId1, paramVal1 ); |
− | smSetParameter( | + | smSetParameter( handle, deviceAddress, paramId2, paramVal1 ); |
− | smSetParameter( | + | smSetParameter( handle, deviceAddress, paramId3, paramVal1 ); |
− | smSetParameter( | + | 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( | + | smAppendSetParamCommandToQueue( handle, paramId1, paramVal1 ); |
− | smAppendSetParamCommandToQueue( | + | smAppendSetParamCommandToQueue( handle, paramId2, paramVal2 ); |
− | smAppendSetParamCommandToQueue( | + | smAppendSetParamCommandToQueue( handle, paramId3, paramVal3 ); |
− | smAppendSetParamCommandToQueue( | + | 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( | + | smGetQueuedSetParamReturnValue( handle, &nul ); |
− | smGetQueuedSetParamReturnValue( | + | smGetQueuedSetParamReturnValue( handle, &nul ); |
− | smGetQueuedSetParamReturnValue( | + | smGetQueuedSetParamReturnValue( handle, &nul ); |
− | smGetQueuedSetParamReturnValue( | + | smGetQueuedSetParamReturnValue( handle, &nul ); |
− | + | ||
− | + | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | In the above example, the ''smExecuteCommandQueue'' is the only line where RS485 is being used thus generating only one write-read latency | + | 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 | |
Following example will: | Following example will: | ||
− | *Initialize read-out parameter | + | *Initialize read-out parameter address so that all further SM commands will return the desired parameter as return value |
− | *Use | + | *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( | + | 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 how large TODOTODO |
− | + | ||
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 ); | ||
− | |||
− | |||
</syntaxhighlight> | </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. | ||
− | |||
− | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
/* Variables: | /* Variables: | ||
− | -readOutParamAddr1 will define the parameter | + | -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 ); | ||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | 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); | ||
− | |||
− | |||
//execute commands over SM bus | //execute commands over SM bus | ||
smExecuteCommandQueue( busHandle, deviceAddress ); | smExecuteCommandQueue( busHandle, deviceAddress ); | ||
− | / | + | //notice that we don't need to change readout parameter addresses here as it we have only one variable to read out |
− | + | ||
+ | //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 | ||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− |