spi ile accelerometer inceleme LIS302DL (stm kit üzerindeki)

Başlatan gambit1244, 02 Şubat 2012, 15:02:03

salih18200

ivme sensöründe büyük titreşimler yoksa birden çok data okuyup ortalamsını alarak açı değerini daha doğru ölçebilirsiniz bence

muhittin_kaplan

Ortalama ile olacak gibi değil. Kontrol Algoritmalarını kullanmak gerek.
Kalman-PID derken Bu aralar Markov Countere Takmış Vaziyetteyim

gambit1244

Alıntı yapılan: salih18200 - 02 Şubat 2012, 22:27:41
lojic analizörün örnekleme frekansınında spi clock frekansına ayarlanması gerekmiyormu

hayır logic clocklari ve enable uçlarına bakarak datayı veriyor sadece
ilk girenmi yüksek değerlikli son girenmi onu belirlemek gerekiyor..
[email]tufan_ozbek@hotmail.com[/email] Yesterday is history. Tomorrow is a mystery. Today is a gift aslında bütün mesele bu.

gambit1244

hocam denemeler güzel kartıda çekseydiniz keşke daha güzel olurdu

hocam haklısınız fakat şuan için ortaya somut birşeyler cıkartmam lazım kalman pid olaylarına girersem 1 ayım gider kafadan yoksa bende çok istiyorum
[email]tufan_ozbek@hotmail.com[/email] Yesterday is history. Tomorrow is a mystery. Today is a gift aslında bütün mesele bu.

iyildirim

Gambit hocam,
Sadece acc. ile olayı görmek için başlangıç yapabilirsiniz. Ama nihai durum için gyro da gerekecektir.

Daha önce bu sensörün biraz farklısını kullanmıştım. (LIS3LV02DL) Datasheetlerden gördüğüm kadarıyla register yapısı ve adresleri ayrı.  Kullandığım işlemci 33f'di ama tanımlamalar açısından sorun çıkaracağını sanmam..  Aynı anda farklı acc. leride denediğimden karıştırmayayım diye register açıklamalarını da yanlarına yazıyordum. Gördüğüm kadarı ile LIS302 de sadece gain ve offset registerleri yok..  Ki onlarla da işimiz yok..

Unutmadan little-big endian kısmına da dikkat etmek gerekiyor.

#define WHO_AM_I         0x0F    //r  00111010     Dummy register 0x3A
#define OFFSET_X         0x16    //rw Calibration Loaded at boot
#define OFFSET_Y         0x17    //rw Calibration Loaded at boot
#define OFFSET_Z         0x18    //rw Calibration Loaded at boot
#define GAIN_X             0x19     //rw Calibration Loaded at boot
#define GAIN_Y             0x1A     //rw Calibration Loaded at boot
#define GAIN_Z             0x1B     //rw Calibration Loaded at boot

#define CTRL_REG1         0x20     //rw 0100000
//76543210
//xx|||||| PD1, PD0 Power Down Control (00: power-down mode; 01, 10, 11: device on)
//||xx|||| DF1, DF0 Decimation Factor Control (00: decimate by 512; 01: decimate by 128; 10: decimate by 32; 11: decimate by  Data Rate --> 00: 40Hz, 01:160Hz, 10:640Hz, 11:2560Hz
//||||x||| ST Self Test Enable (0: normal mode; 1: self-test active)
//|||||x|| Zen Z-axis enable (0: axis off; 1: axis on)
//||||||x| Yen Y-axis enable (0: axis off; 1: axis on)
//|||||||x Xen X-axis enable (0: axis off; 1: axis on)

#define CTRL_REG2         0x21     //rw 0000000
//76543210
//x||||||| FS    Full Scale selection (0: ±2g; 1: ±6g)
//|x|||||| BDU     Block Data Update (0: continuous update; 1: output registers not updated until MSB and LSB reading)
//||x||||| BLE     Big/Little Endian selection (0: little endian; 1: big endian)
//|||x|||| BOOT Reboot memory content 
//||||x||| IEN Interrupt ENable (0: data ready on RDY pad; 1: int req on RDY pad)
//|||||x|| DRDY Enable Data-Ready generation
//||||||x| SIM SPI Serial Interface Mode selection (0: 4-wire interface; 1: 3-wire interface) 
//|||||||x DAS Data Alignment Selection (0: 12 bit right justified; 1: 16 bit left justified)


#define CTRL_REG3         0x22     //rw 0001000
//76543210
//x||||||| ECK External Clock. Default value: 0 (0: clock from internal oscillator; 1: clock from external pad)
//|x|||||| HPDD High Pass filter enabled for Direction Detection. Default value: 0 (0: filter bypassed; 1: filter enabled) 
//||x||||| HPFF High Pass filter enabled for Free-Fall and Wake-Up. Default value: 0 (0: filter bypassed; 1: filter enabled)
//|||x|||| FDS    Filtered Data Selection. Default value: 0 (0: internal filter bypassed; 1: data from internal filter)
//            FDS bit enables (FDS=1) or bypass (FDS=0) the high pass filter in the signal chain of the sensor

//||||xx|| 
//||||||xx CFS1, CFS0 High-pass filter Cut-off Frequency Selection. Default value: 00 
//            (00: Hpc=512
//            01: Hpc=1024
//            10: Hpc=2048
//            11: Hpc=4096)
//CFS1, CFS0 bits defines the coefficient Hpc to be used to calculate the -3dB cut-off frequency of the high pass filter:
//fcutoff = 0.318/Hpc * ODRx/2

#define HP_FILTER RESET 0x23     //r dummy Dummy register
                                //Dummy register. Reading at this address zeroes instantaneously the content of the internal
                                //high pass-filter. Read data is not significant.

#define STATUS_REG         0x27     //rw 00000000
//76543210
//x||||||| ZYXOR X, Y and Z axis Data Overrun
//|x|||||| ZOR Z axis Data Overrun
//||x||||| YOR Y axis Data Overrun
//|||x|||| XOR X axis Data Overrun
//||||x||| ZYXDA X, Y and Z axis new Data Available
//|||||x|| ZDA Z axis new Data Available
//||||||x| YDA Y axis new Data Available
//|||||||x XDA X axis new Data Available






#define OUTX_L             0x28     //r  output    X axis acceleration data LSB
#define OUTX_H             0x29     //r  output X axis acceleration data MSB
#define OUTY_L             0x2A     //r  output Y axis acceleration data LSB
#define OUTY_H             0x2B     //r  output Y axis acceleration data MSB
#define OUTZ_L             0x2C     //r  output Z axis acceleration data LSB
#define OUTZ_H             0x2D     //r  output Z axis acceleration data MSB

#define FF_WU_CFG         0x30     //rw 00000000    Free-fall and inertial wake-up configuration register
//76543210
//x||||||| AOI    And/Or combination of Interrupt events interrupt request. Default value: 0. (0: OR combination of interrupt events; 1: AND combination of interrupt events)
//|x|||||| LIR     Latch interrupt request.                     Default value: 0. (0: interrupt request not latched; 1: interrupt request latched)
//||x||||| ZHIE Enable Interrupt request on Z high event.     Default value: 0. (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
//|||x|||| ZLIE Enable Interrupt request on Z low event.     Default value: 0. (0: disable interrupt request; 1: enable interrupt request on measured accel. value lower than preset threshold)
//||||x||| YHIE Enable Interrupt request on Y high event.     Default value: 0. (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
//|||||x|| YLIE Enable Interrupt request on Y low event.     Default value: 0. (0: disable interrupt request; 1: enable interrupt request on measured accel. value lower than preset threshold)
//||||||x| XHIE Enable Interrupt request on X high event.     Default value: 0. (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
//|||||||x XLIE Enable Interrupt request on X low event.     Default value: 0. (0: disable interrupt request; 1: enable interrupt request on measured accel. value lower than preset threshold)

#define FF_WU_SRC          0x31     //rw 00000000
//76543210
//x||||||| 
//|x|||||| IA    Interrupt Active. Default value: 0    (0: no interrupt has been generated; 1: one or more interrupt event has been generated)
//||x||||| ZH     Z High. Default value: 0             (0: no interrupt; 1: ZH event has occurred)
//|||x|||| ZL    Z Low. Default value: 0             (0: no interrupt; 1: ZL event has occurred)
//||||x||| YH    Y High. Default value: 0            (0: no interrupt; 1: YH event has occurred)
//|||||x|| YL    Y Low. Default value: 0                (0: no interrupt; 1: YL event has occurred)
//||||||x| XH    X High. Default value: 0            (0: no interrupt; 1: XH event has occurred)
//|||||||x XL    X Low. Default value: 0                (0: no interrupt; 1: XL event has occurred)


#define FF_WU_ACK         0x32     //r  dummy Dummy register        Dummy register. If LIR bit in FF_WU_CFG=1 allows the refresh of FF_WU_SRC. Read data is not significant.

#define FF_WU_THS_L     0x34     //rw 00000000    Free-fall / Inertial Wake Up Acceleration Threshold LSB
#define FF_WU_THS_H     0x35     //rw 00000000    Free-fall / Inertial Wake Up Acceleration Threshold MSB

#define FF_WU_DURATION     0x36     //rw 00000000    Minimum duration of the Free-fall/Wake-up event
//                                Set the minimum duration of the free-fall/wake-up event to be recognized
//            Duration(s) = FF_WU_Duration (Dec) / ODR

#define DD_CFG             0x38     //rw 00000000    Direction-detector configuration register
//76543210
//x||||||| IEND    Interrupt enable on Direction change. Default value: 0        (0: disabled; 1: interrupt signal enabled)
//|x|||||| LIR    Latch Interrupt request into DD_SRC reg with the DD_SRC reg cleared by reading    DD_ACK reg. Default value: 0. (0: interrupt request not latched; 1: interrupt request latched)
//||x||||| ZHIE    Enable interrupt generation on Z high event. Default value: 0    (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
//|||x|||| ZLIE    Enable interrupt generation on Z low event. Default value: 0    (0: disable interrupt request; 1: enable interrupt request on measured accel. value lower than preset threshold)
//||||x||| YHIE Enable interrupt generation on Y high event. Default value: 0     (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
//|||||x|| YLIE Enable interrupt generation on Y low event. Default value: 0     (0: disable interrupt request; 1: enable interrupt request on measured accel. value lower than preset threshold)
//||||||x| XHIE Enable interrupt generation on X high event. Default value: 0    (0: disable interrupt request; 1: enable interrupt request on measured accel. value higher than preset threshold)
//|||||||x XLIE Enable interrupt generation on X low event. Default value: 0     (0: disable interrupt request; 1: enable interrupt request on measured accel. value lower than preset threshold)

#define DD_SRC             0x39     //rw 00000000
//76543210
//|x|||||| IA    Interrupt event from direction change.            (0: no direction changes detected; 1: direction has changed from previous measurement)
//||x||||| ZH    Z High. Default value: 0                        (0: Z below THSI threshold;    1: Z accel. exceeding THSE threshold along positive direction of acceleration axis)
//|||x|||| ZL    Z Low. Default value: 0                            (0: Z below THSI threshold;    1: Z accel. exceeding THSE threshold along negative direction of acceleration axis)
//||||x||| YH    Y High. Default value: 0                        (0: Y below THSI threshold;    1: Y accel. exceeding THSE threshold along positive direction of acceleration axis)
//|||||x|| YL    Y Low. Default value: 0                            (0: Y below THSI threshold;    1: Y accel. exceeding THSE threshold along negative direction of acceleration axis)
//||||||x| XH    X High. Default value: 0                        (0: X below THSI threshold;    1: X accel. exceeding THSE threshold along positive direction of acceleration axis)
//|||||||x XL    X Low. Default value: 0                            (0: X below THSI threshold;    1: X accel. exceeding THSE threshold along negative direction of acceleration axis)

#define DD_ACK             0x3A     //r  dummy Dummy register        Dummy register. If LIR bit in DD_CFG=1 allows the refresh of DD_SRC. Read data is not significant.

#define DD_THSI_L         0x3C     //rw 00000000        Direction detection Internal Threshold LSB
#define DD_THSI_H         0x3D     //rw 00000000        Direction detection Internal Threshold MSB
#define DD_THSE_L         0x3E     //rw 00000000        Direction detection External Threshold LSB
#define DD_THSE_H         0x3F     //rw 00000000        Direction detection External Threshold MSB



//ISIMLENDIRME LIS3LV02DQ YA GORE  (SDI, SDO NOT CROSS)

#define SPI2_CS_SELECT LATCbits.LATC4 = 0;
#define SPI2_CS_RELASE LATCbits.LATC4 = 1;

#define SPI2_CS_TRIS  TRISCbits.TRISC4 = 0;    //CS        LIS'E GORE NO CROSS
#define SPI2_SCL_TRIS TRISGbits.TRISG6 = 0;    //SCL
#define SPI2_SDO_TRIS TRISGbits.TRISG7 = 1;    //SD0
#define SPI2_SDI_TRIS TRISGbits.TRISG8 = 0;    //SDI

Çalıştırmak için öncelikle chip'i konfigüre etmeniz gerekiyor. Hangi hızda çalışılacağı, hangi G aralığında çalışlacağı gibi.

Ben chip üzerindeki kesmeleri aktif edip, MCU da düşen kenar kesmesinde SPI okumayı tetikliyordum.   kesmesiz kullanırsanız status registeri okunup, okunamayan veri varmı kontrol etmek gerekiyordu. Aynı şekilde kesmeli kullanımda da kesme geldiği halde registerler okunmazsa kesme üretimi duruyor sonraki veriler okunmuyordu.

chip'i konfigüre ettikten sonra, out registeri adresleri ardışık olduğundan tek seferde X adresinden  itibaren 6 byte okumak yeterli oluyor. Bunun için de chipin continuous update şeklinde konfigüre edilmesi gerekiyordu.


union intcharArr {
    int iVal ; 
    unsigned char cVal[2];
    } ;

union intcharArr aVal[3];


void write_SPI2(unsigned char regAdr, unsigned char regVal)
{    
    unsigned int temp;    

    LIS_InProgress = 1;
    
    SPI2_CS_SELECT

    temp = SPI2BUF;                    
    temp = regAdr & 0b00111111;     //Set bit7 = 0 for write
    SPI2BUF = temp;                    

        Nop();
    while (SPI2STATbits.SPITBF);
    while (!SPI2STATbits.SPIRBF);    
    temp = SPI2BUF;
    
    SPI2BUF = regVal;                

        Nop();
    while (SPI2STATbits.SPITBF);    
    while (!SPI2STATbits.SPIRBF);
    temp = SPI2BUF;

    SPI2_CS_RELASE
    
    LIS_InProgress = 0;
    
}

void read_SPI2(unsigned char regAdr, unsigned char *LISdata, unsigned char LISdataLen)
{    

    int i;
    
    unsigned char temp;

    LIS_InProgress = 1;
    
    temp = SPI2BUF;                    
    temp = regAdr | 0b11000000;     

    SPI2_CS_SELECT


    SPI2BUF = temp;                    
    while (!SPI2STATbits.SPIRBF);    

    for (i=0;i<LISdataLen;i++)
    {
        temp = SPI2BUF;
        SPI2BUF = 0x00;                    
        while (!SPI2STATbits.SPIRBF);    
        (*LISdata) = SPI2BUF;
        *LISdata++;
    }
        
    SPI2_CS_RELASE
    
    LIS_InProgress = 0;
    
    
}

void ReadAccelData_LIS3LV02DL()
{

    union intcharArr Xval, Yval, Zval;

    unsigned char ndx;

    Xval.iVal = 0;
    Yval.iVal = 0;
    Zval.iVal = 0;
    { 
        LISReady = 0;

        read_SPI2(OUTX_L, &aVal[0].cVal[0], 6);

        for(ndx = 0;ndx<3;ndx++)
            aTot[ndx] = aVal[ndx].iVal;

        xaccel.input  = aVal[0].iVal;
        yaccel.input  = aVal[1].iVal;
        zaccel.input  = aVal[2].iVal;

/*        sprintf(outBuf,"aX:  %5i aY:  %5i aZ: %5i \r\n",        aVal[0].iVal,    aVal[1].iVal,    aVal[2].iVal    );
        outString(outBuf);    */

        LISReady = 1;
    
    }


}



void SPI2_Hardware_Test()
{

    union intcharArr in_byte;
    in_byte.iVal = 0;


    SPI2_CS_TRIS    //CS        LIS'E GORE CROSS DEĞİL 
    SPI2_SCL_TRIS    //SCL
    SPI2_SDO_TRIS    //SD0
    SPI2_SDI_TRIS    //SDI
    
    SPI2_CS_RELASE
    
    Init_SPI2();
    delay();
    
    read_SPI2(WHO_AM_I, &in_byte.cVal[0], 1); //Read register WHO_AM_I
    send_Value(in_byte.iVal);
    send_CRLF();
    
    read_SPI2(CTRL_REG1, &in_byte.cVal[0], 1);
    send_Value(in_byte.iVal);
    
    read_SPI2(CTRL_REG2, &in_byte.cVal[0], 1);
    send_Value(in_byte.iVal);
    
    read_SPI2(CTRL_REG3, &in_byte.cVal[0], 1);
    send_Value(in_byte.iVal);
    
    send_CRLF();

//WRITE

//    write_SPI2(CTRL_REG1, 0b10000111); //STOP SELF TEST 40 hz
//    write_SPI1(CTRL_REG1, 0b10010111); //STOP SELF TEST 160 hz
//    write_SPI1(CTRL_REG1, 0b10100111); //STOP SELF TEST 640 hz
//    write_SPI1(CTRL_REG1, 0b10110111); //STOP SELF TEST 2560 hz

    write_SPI2(CTRL_REG1, 0b10000111);    //DEVICE ON XYZ AXIS ENABLE, 40 HZ
    
    write_SPI2(CTRL_REG2, 0b00000000);    //  2g,  CONTINUOUS UPDATE , LITTLE ENDIAN , INTERRUPT ON DATA READY, NO DATA READY INT  12 BIT RIGHT  JUST , 4WIRE SPI, 
    write_SPI2(CTRL_REG2, 0b00000100);  // 2g,  CONTINUOUS UPDATE , LITTLE ENDIAN , INTERRUPT ON DATA READY, DATA READY INT ,  12 BIT RIGHT  JUST , 4WIRE SPI, 
    
    write_SPI2(CTRL_REG3, 0b00000000); //NO EXT CLOCK, HIGH PASS FILTER OFF FOR DIRECTION DETECTION + FREE FALL + DATA , 
    

    read_SPI2(OUTX_L, &in_byte.cVal[0], 2);
    read_SPI2(OUTY_L, &in_byte.cVal[0], 2);
    read_SPI2(OUTZ_L, &in_byte.cVal[0], 2);

    write_SPI2(CTRL_REG2, 0b10000101);    //0 BİT DAS  6G 
    
//    while (1)
    {

//        read_SPI1(STATUS_REG, &in_byte, 1);
//        send_Value(in_byte);
//        if ((in_byte & ==
        if (LISReady == 1)
        {         
            ReadAccelData_LIS3LV02DL();
            LISReady = 0;
        }
//        delay();
        
    }    
}

Kodu pek toparlayamadım ama umarım fikir vermesi açısından faydalı olur. 
Yılbaşı üzeri pek bakamadım ama umarım bundan sonra STMF4'e biraz ilgi gösterebileceğim.

omereliusuk


muhittin_kaplan

Alıntı yapılan: gambit1244 - 02 Şubat 2012, 23:02:28
hocam denemeler güzel kartıda çekseydiniz keşke daha güzel olurdu

hocam haklısınız fakat şuan için ortaya somut birşeyler cıkartmam lazım kalman pid olaylarına girersem 1 ayım gider kafadan yoksa bende çok istiyorum
ekranı capture ettim.

gambit1244

yok yok yok 3 gün oldu ama hala bi gram çözemedim :S

yokmu bi cengaver hocamız şu sensörü nasıl kullanabilceğimiz hakkında bilgisi olan :(((
[email]tufan_ozbek@hotmail.com[/email] Yesterday is history. Tomorrow is a mystery. Today is a gift aslında bütün mesele bu.

muhittin_kaplan

BUnalmış ın örneğini incelemeni tavsiye ederim.

muhittin_kaplan


gambit1244

evet son düzeltilmiş örneği ve datasheetleri iyice kurcaladıktan sonra biraz yol katettim diyebilriim :D
spi iletişim mantığına göre gönderilen 8 bitlik datanın
ilk 2 biti read write ve multiple okuma ayarlarını barındırdığı için bunları gözardı ediyormuşuz
yani logic analyzerden
1000 0111 yani 87 datası geliyorsa bunu
xx00 0111 yani 07 olarak okumamız gerekiyormuş buyüzden kafayı kırıyormuşum bugune kadar nasıl görmedim hayret..
[email]tufan_ozbek@hotmail.com[/email] Yesterday is history. Tomorrow is a mystery. Today is a gift aslında bütün mesele bu.