CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Accelerometer calibrate problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Classic



Joined: 22 Aug 2011
Posts: 6
Location: Thailand

View user's profile Send private message

Accelerometer calibrate problem
PostPosted: Tue Sep 13, 2011 12:12 pm     Reply with quote

Hi, I have a problem about accelerometer MMA7455L and PIC18F2620 with SPI 4 wire in measurement mode. When I showed in LCD at ground plane the results are "XYZ:255 243 78" what's happen?
What do you think? Thank you.

http://www.ccsinfo.com/forum/viewtopic.php?t=37562
http://cache.freescale.com/files/sensors/doc/app_note/AN3745.pdf
http://www.freescale.com/files/sensors/doc/app_note/AN3468.pdf

Code:
#include <18F2620.h>
#fuses HS,NOPROTECT,NOWDT,NOLVP
#use delay(clock=20000000)
#define use_portb_lcd
#include <lcd.c>

#define XOUT8  0x06     
#define YOUT8  0x07   
#define ZOUT8  0x08 
#define STATUS 0x09
#define I2CAD  0x0D
#define MCTL   0x16

#define XOFFL  0x10     //16  Offset drift X value (LSB) (Read/Write)
#define XOFFH  0x11     //17  Offset drift X value (MSB) (Read/Write)
#define YOFFL  0x12     //18  Offset drift Y value (LSB) (Read/Write)
#define YOFFH  0x13     //19  Offset drift Y value (MSB) (Read/Write)
#define ZOFFL  0x14     //20  Offset drift Z value (LSB) (Read/Write)
#define ZOFFH  0x15     //21  Offset drift Z value (MSB) (Read/Write)

#define Acc_CS   PIN_C2   
#define DRDY PIN_C0   

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)
//******************************************
void Acc_init(void);
void Acc_wr(char reg, char dat);
signed char Acc_rd(char reg);
void Calibrate(char Gselect);
void Data_Ready();
//********************************
void Calibrate(char G_Select)
 {
   signed int offs_calib[3]  ;     //keep Value offset X,Y,Z for Calibrate reg.XOFFL-H,YOFFL-H,ZOFFL-H
   signed int offs_ave[3]    ;      //keep Value offset X,Y,Z for Average
   signed char offs_meas[3]  ;       //keep Value offset X,Y,Z for Measurment currunt
   char cnt_run=0,res=0,m,n  ;

   for(m=0;m<3;m++)
     offs_calib[m]=0         ;     //Clear

    Acc_wr(0x16,0x01|(G_Select<<2))  ; //Set up MMa7455L Mode:Measurement

   while((cnt_run++ < 55)&& (res==0))                     //Loop Calibrate Offset 55 time
    {
     for(m=0;m<3;m++)
        offs_ave[m]=0                         ;  //Clear
     for(m=0;m<4;m++)                            //Loop Filter Read data 4 time
      {
        Data_Ready()                          ;  //Check INT1 Conver data Ready ?
       
       offs_meas[0] = Acc_rd(0x06);                    //Read data Output 8 bit GX
       offs_meas[1] = Acc_rd(0x07);                    //Read data Output 8 bit GY
       offs_meas[2] = Acc_rd(0x08);                    //Read data Output 8 bit GZ

       for(n=0;n<3;n++)
         offs_ave[n] += offs_meas[n]         ;  //Total value GX,GY,GZ from reading 4 time
      }
     
     for(m=0;m<3;m++)
       offs_ave[m] /= 4                       ;  //Calculate Average for GX,GY,GZ

     
     if(G_Select == g_2)                       //---- If Select Calibrate Mode 2G (8bit) ----
        offs_ave[2]  -= 0x3F                  ;  //sub value GZ by 63(0x3F) when Z-Axist =1G=63
   
     if(G_Select == g_4)                       //---- If Select Calibrate Mode 4G (8bit)----
        offs_ave[2]  -= 0x1F                  ;  //sub value GZ by 31(0x1F) when Z-Axist =1G=31

     if(G_Select == g_8)                      //---- If Select Calibrate Mode 8G (8bit)----
        offs_ave[2]  -= 0x0F                  ;  //sub value GZ by 15(0x0F) when Z-Axist =1G=15



     for(m=0;m<3;m++)                                             
      {
        if(offs_ave[m]==0)                    //Check Value Average GX,GY,GZ =0
          res++                              ;
      }
     if(res >= 3)                            //if Average GX and GY and GZ =0 Give res=1 Exit Loop While
      {
       res=1 ;
       for(n=0;n<3;n++)
          offs_ave[n] += 1                   ; 
      }
     else
       res =0                                 ; //if Average GX and GY and GZ != 0 Give res=0 Return Read GX,GY,GZ

    for(m=0;m<3;m++)
       offs_calib[m] -= offs_ave[m]           ;

   
    Acc_wr(0x10,offs_cal[0]/256);                  //Write value Calibrate offset byte Low to Reg. XOFFL 
    Acc_wr(0x11,offs_cal[0]%256);                  //Write value Calibrate offset byte HGigh to Reg. XOFFH
 
    Acc_wr(0x12,offs_cal[1]/256);                  //Write value Calibrate offset byte Low to Reg. YOFFL 
    Acc_wr(0x13,offs_cal[1]%256);                  //Write value Calibrate offset byte HGigh to Reg. YOFFH
     
    Acc_wr(0x14,offs_cal[2]/256);                  //Write value Calibrate offset byte Low to Reg. ZOFFL 
    Acc_wr(0x15,offs_cal[2]%256);                  //Write value Calibrate offset byte HGigh to Reg. ZOFFH   
   }
  }
//******************************************
void Acc_wr(char reg, char dat)                   
{
   output_low(Acc_CS);
   spi_write(((reg & 0x3F) << 1) | 0x80);   
   spi_write(dat);                   
   output_high(Acc_CS);       
}
//******************************************
signed char Acc_rd(char reg)
{
   signed char dat;

   output_low(ACC_CS);
   spi_write((reg & 0x3F) << 1);
   dat = spi_read(0);
   output_high(ACC_CS);

return(dat);
}
//*************************************
void Data_Ready()
 {
  while((input(DRDY)& 0x01) != 0x01){;}     
 }

//*************************main********************
main(void)
{
   int Xdata,Ydata,Zdata;
   
   set_tris_b(0x00);
   set_tris_c(0x11);
   delay_ms(500);
   
   output_high(Acc_CS);
   delay_ms(100);
   
   setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_DIV_16);
   
   Calibrate(0x02);//01,02,00
   delay_ms(1000);

   Acc_wr(0x16,0x05); //05,09,01
   delay_ms(500);
     
   lcd_init();
   lcd_send_byte(0,0x01);

   lcd_gotoxy(2,1);
   lcd_putc("Measurement 2G");
   delay_ms(1000);
   
   while(1)
   { 
      Data_Ready();
   
      Xdata = Acc_rd(0x06);
      Ydata = Acc_rd(0x07);
      Zdata = Acc_rd(0x08);
 
      lcd_gotoxy(2,2);
      printf(lcd_putc,"XYZ:%u %u %u ",Xdata,Ydata,Zdata);
      delay_ms(500);
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 13, 2011 4:20 pm     Reply with quote

Your calibration routine is complex. Do you know for sure that it works ?
Why don't you try it without calling the calibration routine, and see what
kind of values you get. Comment it out:
Quote:

// Calibrate(0x02); //01,02,00


In the MMA7455L data sheet, in Table 13, it says these are the expected
output values for a given acceleration. Note that the values are signed.
Code:

2g Mode

      Hex     Decimal
Acc.  Output  Output
-2g   $80     -128
-1g   $C1      -63
 0g   $00        0
+1g   $3F       63
+2g   $7F      127


In the code below, you have declared the X, Y, Z data variables as 'int',
which is an unsigned 8-bit integer in CCS. But it's supposed to
be signed. Change the declaration to 'signed int8'.
Quote:

int Xdata,Ydata,Zdata;


Then in the code below, you are displaying the results as unsigned
decimal values. So if the result was say, -1, which is a very small
acceleration, your code would display it as 255, and you would wonder
what is happening. You need to change the format to "%d".
Also, the size of the displayed number can vary from 1 to 3 characters,
and it could have a minus sign. Because you don't clear the screen
each time, you could have residual characters on the right side of the
lcd after each update. This would cause confusion about the true value
of the Z acceleration. You can fix this by putting \f in front of the XYZ
in the format string. This will clear the lcd screen each pass.
Quote:

while(1)
{
Data_Ready();

Xdata = Acc_rd(0x06);
Ydata = Acc_rd(0x07);
Zdata = Acc_rd(0x08);

lcd_gotoxy(2,2);
printf(lcd_putc,"XYZ:%u %u %u ",Xdata,Ydata,Zdata);
delay_ms(500);
}
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group