Difference between revisions of "Using SimpleMotion scope capture feature"
From Granite Devices Knowledge Wiki
[checked revision] | [checked revision] |
(Created page with "This page is written in Finnish. Translation work in progress. If you need it now, please inquire at Granite Devices support. === Initialization of parameters === *SMP_CA...") (Tag: VisualEditor) |
(→Example) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
This page is written in Finnish. Translation work in progress. If you need it now, please inquire at [[Granite Devices support]]. | This page is written in Finnish. Translation work in progress. If you need it now, please inquire at [[Granite Devices support]]. | ||
− | == | + | ==Alustus, asetetaan skoopin parametrit== |
− | + | ||
− | + | SMP_CAPTURE_BUF_LENGHT - montako samplea kaapataan 1-2048 | |
− | + | ||
− | + | SMP_CAPTURE_SAMPLERATE - näytteistystaajuus (tai sen jakaja). Taajuus on 20kHz/(arvo+1), eli 0=20kHz, 1=10kHz, 2=6.66kHz jne | |
− | + | ||
− | + | SMP_CAPTURE_SOURCE - päälläolevat bitit tässä parametrissa määräävät mitä signaaleja bufferiin kaapataan, seuraavat on saavatilla kaikissa firmisversioissa (samat mitä granityssä valittavissa): | |
− | + | #define CAPTURE_TORQUE_TARGET 1 | |
− | + | #define CAPTURE_TORQUE_ACTUAL 2 | |
− | + | #define CAPTURE_VELOCITY_TARGET 3 | |
− | + | #define CAPTURE_VELOCITY_ACTUAL 4 | |
− | + | #define CAPTURE_POSITION_TARGET 5 | |
− | + | #define CAPTURE_POSITION_ACTUAL 6 | |
− | + | #define CAPTURE_FOLLOW_ERROR 7 | |
− | == | + | #define CAPTURE_OUTPUT_VOLTAGE 8 |
− | + | #define CAPTURE_BUS_VOLTAGE 9 | |
− | + | #define CAPTURE_DEBUG1 19 | |
− | + | #define CAPTURE_DEBUG2 20 | |
− | + | Esim arvoksi tulee 68 (bitit 2 & 6) kanavilla CAPTURE_TORQUE_ACTUAL ja CAPTURE_POSITION_ACTUAL. | |
− | + | ||
− | + | SMP_CAPTURE_TRIGGER - triggeri mikä käynnistää kaappauksen, vaihtoehdot (samat mitä granityssä valittavissa): | |
− | + | #define TRIG_NONE 0 | |
− | + | #define TRIG_INSTANT 1 | |
− | + | #define TRIG_FAULT 2 | |
− | + | #define TRIG_TARGETCHANGE 3 | |
− | + | #define TRIG_TARGETCHANGE_POS 4 | |
+ | #define TRIG_EXTERNAL_INPUT 5 | ||
+ | |||
+ | SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS - tämä tuli vasta FW versiossa 1.6.0. asettaa kaappauksen aloituksen ennen triggausta. arvo prosentteina -1000000...100. Granityt 1.13.0 voi testailla tämän toimintaa. | ||
+ | |||
+ | ==Skoopin luku== | ||
+ | |||
+ | Pollataan arvoa SMP_CAPTURE_STATE, arvot: | ||
+ | 0 - idle (kaappaus valmis tai ei vielä aloitettukaan) | ||
+ | 1 - odottaa triggeriä | ||
+ | 2 - kaappaus käynnissä | ||
+ | |||
+ | Kun kaappaus valmis (käynyt arvoissa !=0 ja sitten 0), ladataan data talteen: | ||
+ | asetetaan SMP_CAPTURE_BUFFER_GET_ADDR = 0 | ||
+ | luetaan parametria SMP_CAPTURE_BUFFER_GET_VALUE yhtä monta kertaa kuin alustuksessa asetettu parametrin arvo SMP_CAPTURE_BUF_LENGHT on | ||
+ | tämän luku palauttaa kaapatut samplet. jos asetettiin kaapattavaksi kanavat a, b ja c, niin luetut arvot tulevat järjestyksesä a0,b0,c0,a1,b1,c1,a2,b2,c2,a3,b3,c3. | ||
+ | |||
+ | ==Example== | ||
+ | <syntaxhighlight lang="c"> | ||
+ | /* Thanks to Oskari Timperi for making part of the code */ | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> //for usleep | ||
+ | #include "simplemotion.h" | ||
+ | |||
+ | smbus handle; | ||
+ | int nodeAddress; | ||
+ | |||
+ | bool setupScope() | ||
+ | { | ||
+ | SM_STATUS status = 0; | ||
+ | |||
+ | status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_BUF_LENGHT, 2048); | ||
+ | status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS, 0); //note, requires on IONI FW 1.6.0 or later | ||
+ | status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_SAMPLERATE, 7); //with IONI sample rate is 20000/(SMP_CAPTURE_SAMPLERATE+1) Hz, so here it is 2500 Hz | ||
+ | status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_SOURCE, BV(CAPTURE_POSITION_ACTUAL)|BV(CAPTURE_BUS_VOLTAGE)); | ||
+ | status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_TRIGGER, TRIG_INSTANT); | ||
+ | status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_STATE, 1); //start capture | ||
+ | |||
+ | if(status!=SM_OK) | ||
+ | { | ||
+ | //error | ||
+ | return false; | ||
+ | } | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | //parameters: nsamples=number of samples to read 1-2048, samples=pointer to buffer with at least nsamples length | ||
+ | bool downloadScope( int nsamples, int *samples ) | ||
+ | { | ||
+ | smint32 retval; | ||
+ | int samplesread=0, storepos=0; | ||
+ | SM_STATUS smStat=0; | ||
+ | |||
+ | //setup for scope reading | ||
+ | smStat|=smAppendSMCommandToQueue( handle, SMPCMD_SET_PARAM_ADDR, SMP_RETURN_PARAM_LEN ); | ||
+ | smStat|=smAppendSMCommandToQueue( handle, SMPCMD_24B, SMPRET_32B );//read 32 bit (values capped to 30 bits) samples | ||
+ | smStat|=smAppendSMCommandToQueue( handle, SMPCMD_SET_PARAM_ADDR, SMP_RETURN_PARAM_ADDR ); | ||
+ | smStat|=smAppendSMCommandToQueue( handle, SMPCMD_24B, SMP_CAPTURE_BUFFER_GET_VALUE ); //read at get_value param | ||
+ | smStat|=smAppendSMCommandToQueue( handle, SMPCMD_SET_PARAM_ADDR, SMP_CAPTURE_BUFFER_GET_ADDR ); //set store address to get_addr | ||
+ | smStat|=smExecuteCommandQueue(handle,nodeAddress); | ||
+ | smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); | ||
+ | smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); | ||
+ | smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); | ||
+ | smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); | ||
+ | smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); | ||
+ | |||
+ | //loop to read samples | ||
+ | while(samplesread<nsamples) | ||
+ | { | ||
+ | int i; | ||
+ | int samplestofetch=nsamples-samplesread; | ||
+ | if(samplestofetch>30)samplestofetch=30;//maximum per one SM cycle (4*30=120 bytes=max payload) | ||
+ | |||
+ | //add read param commands to queue | ||
+ | for(i=0;i<samplestofetch;i++) | ||
+ | { | ||
+ | smStat|=smAppendSMCommandToQueue( handle, SMPCMD_24B, samplesread ); | ||
+ | samplesread++; | ||
+ | } | ||
+ | |||
+ | //transmit & redeive over SM bus | ||
+ | smStat|=smExecuteCommandQueue(handle,nodeAddress); | ||
+ | |||
+ | //read values from return data queue | ||
+ | for(i=0;i<samplestofetch;i++) | ||
+ | { | ||
+ | smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); | ||
+ | samples[storepos++]=retval; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //read one dummy variable just to cause SMP_RETURN_PARAM_ADDR to change to non-SMP_CAPTURE_BUFFER_GET_VALUE so next time we read data, we get it all from beginning | ||
+ | smStat |= smRead1Parameter(handle, nodeAddress, SMP_NULL, &retval ); | ||
+ | |||
+ | if(smStat!=SM_OK) | ||
+ | return false; | ||
+ | |||
+ | return true; | ||
+ | } | ||
+ | |||
+ | SM_STATUS scopeWait() | ||
+ | { | ||
+ | smint32 state; | ||
+ | |||
+ | //loop until SMP_CAPTURE_STATE is 0 (scope idle) | ||
+ | while (true) | ||
+ | { | ||
+ | SM_STATUS status = smRead1Parameter(handle, nodeAddress, SMP_CAPTURE_STATE, &state); | ||
+ | |||
+ | if (status != SM_OK) | ||
+ | return status; | ||
+ | |||
+ | fprintf(stderr, "scope state: %d\n", state); | ||
+ | |||
+ | if (state == 0) | ||
+ | { | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | usleep(100000); | ||
+ | } | ||
+ | |||
+ | return SM_OK; | ||
+ | } | ||
+ | |||
+ | |||
+ | int main( void ) | ||
+ | { | ||
+ | const char *portName="COM3"; //bus device name | ||
+ | nodeAddress = 4; //SM device address | ||
+ | int samples[2048]; | ||
+ | |||
+ | fprintf(stderr, "opening bus %s\n", portName); | ||
+ | handle = smOpenBus(portName); | ||
+ | |||
+ | if (handle < 0) | ||
+ | { | ||
+ | fprintf(stderr, "could not open bus: %s\n", portName); | ||
+ | return -4; | ||
+ | } | ||
+ | |||
+ | if(setupScope()==false) | ||
+ | return -1; | ||
+ | |||
+ | if(scopeWait()!=SM_OK) | ||
+ | return -2; | ||
+ | |||
+ | if(downloadScope( 2048, samples )==false) | ||
+ | return -3; | ||
+ | |||
+ | //sample list will be repeating list of samples defined to SMP_CAPTURE_SOURCE. | ||
+ | //I.e if we capture 3 channels A, B and C, then samples will contain A0,B0,C0,A1,B1,C1,A2,B3,C3 etc | ||
+ | for( int i=0; i<2048; i++) | ||
+ | { | ||
+ | fprintf(stderr, "samples[%d]=%d\n", i, samples[i]); | ||
+ | } | ||
+ | |||
+ | fprintf(stderr, "All done\n"); | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
[[Category:SimpleMotion]] | [[Category:SimpleMotion]] |
Latest revision as of 14:19, 6 September 2017
This page is written in Finnish. Translation work in progress. If you need it now, please inquire at Granite Devices support.
Alustus, asetetaan skoopin parametrit[edit | edit source]
SMP_CAPTURE_BUF_LENGHT - montako samplea kaapataan 1-2048
SMP_CAPTURE_SAMPLERATE - näytteistystaajuus (tai sen jakaja). Taajuus on 20kHz/(arvo+1), eli 0=20kHz, 1=10kHz, 2=6.66kHz jne
SMP_CAPTURE_SOURCE - päälläolevat bitit tässä parametrissa määräävät mitä signaaleja bufferiin kaapataan, seuraavat on saavatilla kaikissa firmisversioissa (samat mitä granityssä valittavissa): #define CAPTURE_TORQUE_TARGET 1 #define CAPTURE_TORQUE_ACTUAL 2 #define CAPTURE_VELOCITY_TARGET 3 #define CAPTURE_VELOCITY_ACTUAL 4 #define CAPTURE_POSITION_TARGET 5 #define CAPTURE_POSITION_ACTUAL 6 #define CAPTURE_FOLLOW_ERROR 7 #define CAPTURE_OUTPUT_VOLTAGE 8 #define CAPTURE_BUS_VOLTAGE 9 #define CAPTURE_DEBUG1 19 #define CAPTURE_DEBUG2 20 Esim arvoksi tulee 68 (bitit 2 & 6) kanavilla CAPTURE_TORQUE_ACTUAL ja CAPTURE_POSITION_ACTUAL.
SMP_CAPTURE_TRIGGER - triggeri mikä käynnistää kaappauksen, vaihtoehdot (samat mitä granityssä valittavissa): #define TRIG_NONE 0 #define TRIG_INSTANT 1 #define TRIG_FAULT 2 #define TRIG_TARGETCHANGE 3 #define TRIG_TARGETCHANGE_POS 4 #define TRIG_EXTERNAL_INPUT 5
SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS - tämä tuli vasta FW versiossa 1.6.0. asettaa kaappauksen aloituksen ennen triggausta. arvo prosentteina -1000000...100. Granityt 1.13.0 voi testailla tämän toimintaa.
Skoopin luku[edit | edit source]
Pollataan arvoa SMP_CAPTURE_STATE, arvot: 0 - idle (kaappaus valmis tai ei vielä aloitettukaan) 1 - odottaa triggeriä 2 - kaappaus käynnissä
Kun kaappaus valmis (käynyt arvoissa !=0 ja sitten 0), ladataan data talteen: asetetaan SMP_CAPTURE_BUFFER_GET_ADDR = 0 luetaan parametria SMP_CAPTURE_BUFFER_GET_VALUE yhtä monta kertaa kuin alustuksessa asetettu parametrin arvo SMP_CAPTURE_BUF_LENGHT on tämän luku palauttaa kaapatut samplet. jos asetettiin kaapattavaksi kanavat a, b ja c, niin luetut arvot tulevat järjestyksesä a0,b0,c0,a1,b1,c1,a2,b2,c2,a3,b3,c3.
Example[edit | edit source]
/* Thanks to Oskari Timperi for making part of the code */ #include <stdio.h> #include <unistd.h> //for usleep #include "simplemotion.h" smbus handle; int nodeAddress; bool setupScope() { SM_STATUS status = 0; status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_BUF_LENGHT, 2048); status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_BEFORE_TRIGGER_PERCENTS, 0); //note, requires on IONI FW 1.6.0 or later status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_SAMPLERATE, 7); //with IONI sample rate is 20000/(SMP_CAPTURE_SAMPLERATE+1) Hz, so here it is 2500 Hz status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_SOURCE, BV(CAPTURE_POSITION_ACTUAL)|BV(CAPTURE_BUS_VOLTAGE)); status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_TRIGGER, TRIG_INSTANT); status |= smSetParameter(handle, nodeAddress, SMP_CAPTURE_STATE, 1); //start capture if(status!=SM_OK) { //error return false; } return true; } //parameters: nsamples=number of samples to read 1-2048, samples=pointer to buffer with at least nsamples length bool downloadScope( int nsamples, int *samples ) { smint32 retval; int samplesread=0, storepos=0; SM_STATUS smStat=0; //setup for scope reading smStat|=smAppendSMCommandToQueue( handle, SMPCMD_SET_PARAM_ADDR, SMP_RETURN_PARAM_LEN ); smStat|=smAppendSMCommandToQueue( handle, SMPCMD_24B, SMPRET_32B );//read 32 bit (values capped to 30 bits) samples smStat|=smAppendSMCommandToQueue( handle, SMPCMD_SET_PARAM_ADDR, SMP_RETURN_PARAM_ADDR ); smStat|=smAppendSMCommandToQueue( handle, SMPCMD_24B, SMP_CAPTURE_BUFFER_GET_VALUE ); //read at get_value param smStat|=smAppendSMCommandToQueue( handle, SMPCMD_SET_PARAM_ADDR, SMP_CAPTURE_BUFFER_GET_ADDR ); //set store address to get_addr smStat|=smExecuteCommandQueue(handle,nodeAddress); smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); //loop to read samples while(samplesread<nsamples) { int i; int samplestofetch=nsamples-samplesread; if(samplestofetch>30)samplestofetch=30;//maximum per one SM cycle (4*30=120 bytes=max payload) //add read param commands to queue for(i=0;i<samplestofetch;i++) { smStat|=smAppendSMCommandToQueue( handle, SMPCMD_24B, samplesread ); samplesread++; } //transmit & redeive over SM bus smStat|=smExecuteCommandQueue(handle,nodeAddress); //read values from return data queue for(i=0;i<samplestofetch;i++) { smStat|=smGetQueuedSMCommandReturnValue( handle, &retval ); samples[storepos++]=retval; } } //read one dummy variable just to cause SMP_RETURN_PARAM_ADDR to change to non-SMP_CAPTURE_BUFFER_GET_VALUE so next time we read data, we get it all from beginning smStat |= smRead1Parameter(handle, nodeAddress, SMP_NULL, &retval ); if(smStat!=SM_OK) return false; return true; } SM_STATUS scopeWait() { smint32 state; //loop until SMP_CAPTURE_STATE is 0 (scope idle) while (true) { SM_STATUS status = smRead1Parameter(handle, nodeAddress, SMP_CAPTURE_STATE, &state); if (status != SM_OK) return status; fprintf(stderr, "scope state: %d\n", state); if (state == 0) { break; } usleep(100000); } return SM_OK; } int main( void ) { const char *portName="COM3"; //bus device name nodeAddress = 4; //SM device address int samples[2048]; fprintf(stderr, "opening bus %s\n", portName); handle = smOpenBus(portName); if (handle < 0) { fprintf(stderr, "could not open bus: %s\n", portName); return -4; } if(setupScope()==false) return -1; if(scopeWait()!=SM_OK) return -2; if(downloadScope( 2048, samples )==false) return -3; //sample list will be repeating list of samples defined to SMP_CAPTURE_SOURCE. //I.e if we capture 3 channels A, B and C, then samples will contain A0,B0,C0,A1,B1,C1,A2,B3,C3 etc for( int i=0; i<2048; i++) { fprintf(stderr, "samples[%d]=%d\n", i, samples[i]); } fprintf(stderr, "All done\n"); return 0; }