Difference between revisions of "Using SimpleMotion scope capture feature"

From Granite Devices Knowledge Wiki
Jump to: navigation, search
[checked revision][checked revision]
(Example)
 
(3 intermediate revisions by the same user not shown)
Line 4: Line 4:
  
 
     SMP_CAPTURE_BUF_LENGHT - montako samplea kaapataan 1-2048
 
     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_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):
 
     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_TARGET 1
Line 35: Line 37:
 
         1 - odottaa triggeriä
 
         1 - odottaa triggeriä
 
         2 - kaappaus käynnissä
 
         2 - kaappaus käynnissä
 +
 
     Kun kaappaus valmis (käynyt arvoissa !=0 ja sitten 0), ladataan data talteen:
 
     Kun kaappaus valmis (käynyt arvoissa !=0 ja sitten 0), ladataan data talteen:
 
         asetetaan SMP_CAPTURE_BUFFER_GET_ADDR = 0
 
         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
 
         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.
 
             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;
}