Using SimpleMotion scope capture feature

From Granite Devices Knowledge Wiki
Jump to: navigation, search

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;
}

In no event the Product Information or parts hereof shall be regarded as guarantee of conditions or characteristics. The Product Information or any part thereof may also not be regarded as a warranty of any kind. No liability of any kind shall be assumed by Author with respect to Product Information or any use made by you thereof, nor shall Author indemnify you against or be liable for any third party claims with respect to such information or any use thereof.

As content of this Wiki may be edited by user community, Granite Devices Oy or it's affiliates do not take any responsibility of the contents of this Wiki. Use information at your own risk. However, Granite Devices staff attempts to review all changes made to this Wiki and keep information trustworthy.

Without written consent, Granite Devices' Products or Intellectual Property shall not be used in situations or installations where living beings, material property, or immaterial property could be harmed by the operation, features or failures of Product. Products may only be used in a way where hazards like moving parts, electric shock, laser radiation, or fire can't be realized even if the content of this Wiki would suggest otherwise.