I've a problem with my Accelerometer in my I2C program(PIC32)

Discussion in 'Embedded Systems and Microcontrollers' started by Sielo, May 26, 2011.

  1. Sielo

    Thread Starter New Member

    May 26, 2011
    3
    0
    Hi, first of all i'm sorry for my english i hope u can undestand what i'll say.
    I'm having problem with my program, i'm trying to do a balancing robot with acc and gyro using PIC32 and I2C.
    I tested this I2C routine and it seems to work but something mess up with the data that i read with my acc i've done a cycle to test the ±G switching by moving my platform,it seem to "fall" always by the same side.
    The acc i'm using is MMA7455L.
    And this is the data sheet link http://www.freescale.com/files/sensors/doc/data_sheet/MMA7455L.pdf
    Sorry for some italian comment but i think the I2C routine doesn't need comment i've comment in english only Cmotory,Inizacc and Elabacc.
    This is my Code:
    Code ( (Unknown Language)):
    1. #include<plib.h>
    2. #include<peripheral/int.h>
    3. #include<p32xxxx.h>
    4. #pragma config POSCMOD=XT, FNOSC=PRIPLL
    5. #pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1
    6. #pragma config FPBDIV=DIV_2, FWDTEN=OFF, CP=OFF, BWP=OFF
    7.  
    8. #define LCDDATA 1
    9. #define LCDCMD  0
    10. #define PMDATA  PMDIN
    11. int len,reg_addr,PER_ADDR,Dgyro,Dacc,Dgyroold,DgyroM,Direz;
    12. unsigned char dato;
    13. void configPIC ()
    14. {
    15. #define SYSTEM_CLK (80000000L)
    16. SYSTEMConfigPerformance(SYSTEM_CLK);  
    17. mJTAGPortEnable(DEBUG_JTAGPORT_OFF);  // JTAG disabled
    18. TRISE=0x00;         // Set TRISE to all output
    19. LATE=0x00;         // Init all the E pin to 0
    20. }
    21. void eepromInit(void)
    22. {
    23. I2CConfigure(I2C2, I2C_ENABLE_SLAVE_CLOCK_STRETCHING|I2C_ENABLE_HIGH_SPEED);
    24. I2CSetFrequency(I2C2,80000000L,40000);           //Set the F=4Khz
    25. I2CEnable(I2C2, TRUE);                                   //I2C Enable
    26. }
    27. void eepromRead(unsigned int PER_ADDR, unsigned int reg_addr,unsigned char *buf)
    28. {
    29. StartI2C2();           //Avvio L'I2C
    30. IdleI2C2();            //Metto in idle aspettando un nuovo comando
    31. MasterWriteI2C2(PER_ADDR | 0);       //Chiamo la periferica desiderata in scrittura
    32. IdleI2C2();            
    33. if (I2C2STATbits.ACKSTAT)return;      //Controllo se è ritornato un ack se no rinizio la procedura
    34. MasterWriteI2C2(reg_addr);        //Chiamo il registro interno alla perifica
    35. IdleI2C2();
    36. if(I2C2STATbits.ACKSTAT) return;      //Controllo se è ritornato un ack se no rinizio la procedura
    37. RestartI2C2();           //Eseguo un Restart per poter chiamare la funzione in lettura altrimenti creerei un situazione di conflitto sui bus
    38. IdleI2C2();
    39. MasterWriteI2C2(PER_ADDR | 1);       //Chiamo la periferica desiderata in lettura
    40. IdleI2C2();
    41. if(I2C2STATbits.ACKSTAT) return;      //Controllo se è ritornato un ack se no rinizio la procedura
    42. I2C2CONbits.RCEN = 1;
    43. while(!DataRdyI2C2());         //Inizio ricezione dati
    44. *buf = I2C2RCV;           //Metto i dati nel buffer
    45. I2C2CONbits.ACKDT = 1;
    46. I2C2CONbits.ACKEN = 1;
    47. while(I2C2CONbits.ACKEN==1);       //inizio la procedura di ack per arrivare alla fine della trasmissione
    48. StopI2C2();
    49. IdleI2C2();        
    50. }
    51. void eepromWrite(unsigned int PER_ADDR, unsigned int reg_addr, unsigned char *buf)
    52. {
    53.  StartI2C2();
    54.  IdleI2C2();
    55.  
    56.  MasterWriteI2C2(PER_ADDR | 0);           //Chiamo la periferica in scrittura
    57.  IdleI2C2();
    58.  
    59.  if (I2C2STATbits.ACKSTAT)return;    //Richiedo un ack
    60.  MasterWriteI2C2(reg_addr);               //Invio l'indirizzo del registro della periferica
    61.  IdleI2C2();
    62.  
    63.  MasterWriteI2C2(*buf);       //Scrivo il dato inserito nella variabile puntata da buf
    64.  IdleI2C2();
    65.  if (I2C2STATbits.ACKSTAT)return;          //Richiedo un ack
    66.  
    67.   StopI2C2();
    68.   IdleI2C2();
    69.  while(1)
    70.  {
    71.   StartI2C2();
    72.   IdleI2C2();
    73.   MasterWriteI2C2(PER_ADDR | 0);       //Chiamo la periferica in scrittura
    74.   IdleI2C2();
    75.  
    76.  if (I2C2STATbits.ACKSTAT==0) break;   //Se ritorna un ack esco dal ciclo
    77.   StopI2C2();
    78.   IdleI2C2();
    79.   }
    80.  
    81.  StopI2C2();
    82.  IdleI2C2();
    83. }
    84.  
    85. void Inizacc ()
    86. {
    87.  int indirizzo=0x3A;        
    88.  dato=0b00000101;
    89.  eepromWrite(indirizzo,0x16,&dato);     //2G mode  
    90.  dato=0b00000000;
    91.  eepromWrite(indirizzo,0x18,&dato);     //All axis enable
    92.  dato=0b00000000;
    93.  eepromWrite(indirizzo,0x19,&dato);     //Motion Detector
    94. }
    95.  
    96. void Elabacc ()
    97. {
    98.  int indirizzo=0x3A;
    99.  eepromRead(indirizzo,0x08,&dato); //Z axis 8 bit, only one avaible in measurament mode
    100.  Dacc=dato;
    101.  }
    102.  
    103. void CMotori ()
    104. {
    105.  int Stab;
    106.  Stab=Dacc;                    //Var to avoid activating motors while in stability
    107.  if(Stab=0) return;
    108.  Direz=Dacc && 0x80;     //Mask MSB to compare it (MSB change with the G polarity +G=0 -G=1).
    109.  if (Direz = 0)
    110.  {
    111.   while(Direz=0)             //while falling one that side.
    112.   {
    113.   LATEbits.LATE0=1;        //Enable the motors supply and direction
    114.   LATEbits.LATE1=1;
    115.   LATEbits.LATE2=0;
    116.   Elabacc();                       //Check the acc data
    117.   Direz=Dacc && 0x80;     //Put new data in direz
    118.   }  
    119.  }
    120.  else
    121.  {
    122.   while(Direz=0x80)        //same as before but for other side
    123.   {
    124.   LATEbits.LATE0=1;
    125.   LATEbits.LATE1=0;
    126.   LATEbits.LATE2=1;
    127.   Elabacc();
    128.   Direz=Dacc && 0x80;
    129.   }
    130.  }
    131.  
    132. }
    133. main (void)
    134. {
    135.  configPIC();            
    136.  eepromInit();          
    137.  Inizgyro();               //function removed in this because i'm sure that's right and i don't use it in this example
    138.  Inizacc();
    139.  while(1)
    140.  {
    141.  Elabacc();
    142.  CMotori();  
    143.  }
    144. }
    145.  
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    I'm just taking a wild guess here.

    in void Elabacc () you perform

    Dacc=dato;

    where dato is a char and Dacc is an int.

    Later in void CMotori () you perform:

    Direz=Dacc && 0x80; //Mask MSB to compare it (MSB change with the G polarity +G=0 -G=1).

    Now depending on your compiler you may need to do something different, see if you can hook a debugger on there to see what values you actually have. It may be that converting the char dato to the int Dacc is extending the sign bit across the full width of the int.
     
    Sielo likes this.
  3. Sielo

    Thread Starter New Member

    May 26, 2011
    3
    0
    i'm using MPLAB tomorrow morning i'll try because now it's a bit late for me
    I'll let u know if it works!
    Thank you for the help ^^
     
  4. Sielo

    Thread Starter New Member

    May 26, 2011
    3
    0
    It wasn't a problem of Char or int!
    I'm an idiot... i've done && to do normal AND instead of & and = to compare instead of == now it works!
     
Loading...