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==== |
| + | {{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. |
| | | |
− | ===Low level queued commands===
| |
− | 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 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. |
| <syntaxhighlight lang="c"> | | <syntaxhighlight lang="c"> |
| + | |
| + | |
| /*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 119: |
| 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 136: |
| smGetQueuedSMCommandReturnValue( busHandle,&readout2 ); | | smGetQueuedSMCommandReturnValue( busHandle,&readout2 ); |
| smGetQueuedSMCommandReturnValue( busHandle,&readout3 ); | | smGetQueuedSMCommandReturnValue( busHandle,&readout3 ); |
− |
| |
− | //TODO add some SM error checking in appropriate places
| |
− | </syntaxhighlight>
| |
− |
| |
− | 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.
| |
− |
| |
− | Initialization:
| |
− | <syntaxhighlight lang="c">
| |
− | /* Variables:
| |
− | -readOutParamAddr1 will define the parameter number to be read out into readout1
| |
− | */
| |
− | smint32 nul, readOutParamAddr1=SMP_ACTUAL_POSITION_FB;
| |
− |
| |
− | /*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.
| |
− |
| |
− | Note: we do it the low level way in this case because SMPCMD_SETPARAMADD is
| |
− | not available on higher level SM functions*/
| |
− |
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_SETPARAMADDR, SMP_RETURN_PARAM_LEN ); //2b
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_24B, SMPRET_24B );//3b
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_SETPARAMADDR, SMP_RETURN_PARAM_ADDR );//2b
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_24B, readOutParamAddr2 );//3b
| |
− |
| |
− | //execute commands over SM bus
| |
− | smExecuteCommandQueue( busHandle, deviceAddress );
| |
− |
| |
− | //must get all inserted commands from buffer
| |
− | smGetQueuedSMCommandReturnValue( busHandle, &nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle, &nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle, &nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle, &nul );
| |
− |
| |
− | //TODO add some SM error checking in appropriate places
| |
− | </syntaxhighlight>
| |
− |
| |
− | Frequently called function with writing 3 variables and reading one in one bus transfer:
| |
− | <syntaxhighlight lang="c">
| |
− | /* Variables:
| |
− | -paramValue1-3 are the parameter values written to parameter numbers defined in paramAddr1-3
| |
− | -readOutParamAddr1-3 will define the parameter numbers to read out into readout1-3
| |
− | */
| |
− | int paramAddr1=SMP_DEBUGPARAM4;
| |
− | int paramAddr2=SMP_DEBUGPARAM5;
| |
− | int paramAddr3=SMP_DEBUGPARAM6;
| |
− | int paramValue1=100;
| |
− | int paramValue2=200;
| |
− | int paramValue3=300;
| |
− | smint32 nul, readout1;
| |
− |
| |
− | //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);
| |
− |
| |
− | //set an new parameter number where next values are written. This line consumes 2 bytes of outbound payload
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_SETPARAMADDR, paramAddr2 );
| |
− |
| |
− | //write the parameter value to previously set parameter address. SMPCMD_24B consumes 3 bytes of outbound payload
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_24B, paramValue2);
| |
− |
| |
− | //set an new parameter number where next values are written. This line consumes 2 bytes of outbound payload
| |
− | smAppendSMCommandToQueue( busHandle, SMPCMD_SETPARAMADDR, paramAddr3 );
| |
− |
| |
− | //write the parameter value to previously set parameter address. SMPCMD_32B consumes 4 bytes of outbound payload
| |
− | 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
| |
− | smExecuteCommandQueue( busHandle, deviceAddress );
| |
− |
| |
− | /*read value commands (one per each append command before execute). Size of inbound payload depends on
| |
− | what was set to SMP_RETURN_PARAM_LEN at initialization. In this case 3 bytes per return value (total 6x3). */
| |
− | smGetQueuedSMCommandReturnValue( busHandle,&nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle,&nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle,&nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle,&nul );
| |
− | smGetQueuedSMCommandReturnValue( busHandle,&nul );
| |
− | 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]]
| |