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 CCS Technical Support

18F26J50 and MMA8452 accelerometer reading FF

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



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

18F26J50 and MMA8452 accelerometer reading FF
PostPosted: Wed Apr 25, 2012 4:55 am     Reply with quote

hi,
I wrote 18f26j50 and mma8452 accelerometer code. But seen FF on screen.
I changed i2c_RegRead(SlaveAddressIIC, MMA8452_OFF_X) result is same. where is mistake?
Thanks..


Code:



#include <18F26J50.h>
#fuses INTRC_IO,NOPROTECT,NODEBUG,NOCPUDIV
#use delay(clock=8000000)
#include <lcdaccess.c>
#use i2c(master, sda=PIN_B5, scl=PIN_B4, force_hw)
#define SlaveAddressIIC       0x38
#define CTRL_REG1             0x2A
#define CTRL_REG2             0x2B
#define CTRL_REG3             0x2C
#define CTRL_REG4             0x2D
#define CTRL_REG5             0x2E
#define MMA8452_OFF_X         0x2F
#define MMA8452_OFF_Y         0x30
#define MMA8452_OFF_Z         0x31
///////////////////////////////////
#define ASLP_RATE1_MASK       0x80
#define ASLP_RATE0_MASK       0x40
#define DR2_MASK              0x20
#define DR1_MASK              0x10
#define DR0_MASK              0x08
#define LNOISE_MASK           0x04
#define FREAD_MASK            0x02
#define ACTIVE_MASK           0x01
#define ASLP_RATE_MASK        0xC0
#define DR_MASK               0x38
//                     
#define ASLP_RATE_20MS        0x00
#define ASLP_RATE_80MS        ASLP_RATE0_MASK
#define ASLP_RATE_160MS       ASLP_RATE1_MASK
#define ASLP_RATE_640MS       ASLP_RATE1_MASK+ASLP_RATE0_MASK
//
#define DATA_RATE_1250US      0x00
#define DATA_RATE_2500US      DR0_MASK
#define DATA_RATE_5MS         DR1_MASK
#define DATA_RATE_10MS        DR1_MASK+DR0_MASK
#define DATA_RATE_20MS        DR2_MASK
#define DATA_RATE_80MS        DR2_MASK+DR0_MASK
#define DATA_RATE_160MS       DR2_MASK+DR1_MASK
#define DATA_RATE_640MS       DR2_MASK+DR1_MASK+DR0_MASK
/*
**  XYZ_DATA_CFG Sensor Data Configuration Register
*/
#define XYZ_DATA_CFG_REG      0x0E
//
#define HPF_OUT_BIT           Bit._4
#define FS1_BIT               Bit._1
#define FS0_BIT               Bit._0
//
#define HPF_OUT_MASK          0x10
#define FS1_MASK              0x02
#define FS0_MASK              0x01
#define FS_MASK               0x03
#define FULL_SCALE_8G         FS1_MASK
#define FULL_SCALE_4G         FS0_MASK
#define FULL_SCALE_2G         0x00
byte value[6];                              // working value result scratchpad
byte full_scale;                            // current accelerometer full scale setting




void i2c_RegWrite(byte address, byte reg,byte val)
{
                             
      i2c_start();
      i2c_write(address);
      i2c_write(reg);
      i2c_write(val);
      i2c_stop();
}
/////////////////////////////
byte i2c_RegRead(byte address, byte reg)
{
  byte b;
 
  i2c_start();                                  // Send Start
  i2c_write(address);                      // Send IIC "Write" Address
  i2c_write(reg);                          // Send Register
  i2c_start();                             // Send Repeat Start
  i2c_write(address+1);                    // Send IIC "Read" Address
  b = i2c_read(1);                         // *** Dummy read: reads "IIC_ReadAddress" value ***
  b = i2c_read(1);                         // Read Register Value
  i2c_stop();                                   // Send Stop
  return b;
}
////////////////////////////
void MMA8452_Active ()
{
  i2c_RegWrite(SlaveAddressIIC, CTRL_REG1, (i2c_RegRead(SlaveAddressIIC, CTRL_REG1) | ACTIVE_MASK));
}
///////////////////////////
void MMA8452_Standby (void)
{
  byte n;
  /*
  **  Read current value of System Control 1 Register.
  **  Put sensor into Standby Mode.
  **  Return with previous value of System Control 1 Register.
  */
  n = i2c_RegRead(SlaveAddressIIC, CTRL_REG1);
  i2c_RegWrite(SlaveAddressIIC, CTRL_REG1, n & ~ACTIVE_MASK);
}
////////////////////////////////////
void MMA8452_Init (void)
{
  MMA8452_Standby();
  /*
  **  Configure sensor for:
  **    - Sleep Mode Poll Rate of 50Hz (20ms)
  **    - System Output Data Rate of 200Hz (5ms)
  **    - Full Scale of +/-2g
  */
  i2c_RegWrite(SlaveAddressIIC, CTRL_REG1, ASLP_RATE_20MS+DATA_RATE_5MS);
  i2c_RegWrite(SlaveAddressIIC, XYZ_DATA_CFG_REG, FULL_SCALE_2G);
}
/////////////////////////////


void main(void)
{
   lcd_init();
   output_high(PIN_A3);
   MMA8452_Init();
   MMA8452_Active();
   full_scale= FULL_SCALE_2G;

   while(true)
   {
     
   
         printf(lcd_putc,"\fivme:%x",i2c_RegRead(SlaveAddressIIC, MMA8452_OFF_X));
     
      delay_ms(100);


   }       
   
}//main
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Apr 25, 2012 5:04 am     Reply with quote

1) you don't specify the speed of the I2C bus..so can the device accept the default speed ??

2) do you have the correct pullup resistors on the I2C bus? Val;ue depends upon Vcc,distance and of course speed(which we don't know).


Ttemah(sp) has a nice I2C 'sniffer' program here, you should download it to verify your hardware.
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Wed Apr 25, 2012 5:13 am     Reply with quote

it have pull up registor because this is module.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Wed Apr 25, 2012 7:29 am     Reply with quote

Just because it is a 'module', does not automatically imply it has the pull up resistors. You need to check the data for the specific 'module'. Some are built to connect to ports that already have the resistors, so do not have them on the board, or they are optional....
How have you got the supply connected?. There are two supply pins to the chip (and presumably the module). You need both to be present.
Do you know how the module has the SA0 pin connected?. The chip has two different slave addresses possible. 0x38 - if SA0 is low, and 0x3A, if SA0 is high.
Then your read code appears faulty. You send the register address, and then read twice, saying "Dummy read: reads "IIC_ReadAddress" value" for the first read. This is not the case. The value you read after sending the address is the data on the very next transaction. A dummy read like this is necessary with SSP, where the master receives 'back' a dummy byte when sending, but not with I2C.

Best Wishes
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Thu Apr 26, 2012 3:53 pm     Reply with quote

Code:

#include <18F26J50.h>
#fuses INTRC_IO,NOPROTECT,NODEBUG,NOCPUDIV
#use delay(clock=8000000)
#include <lcdaccess.c>
#use i2c(master, sda=PIN_B5, scl=PIN_B4, force_hw)
//#define MMA8452_ADDRESS 0x1C //SA0=0
#define MMA8452_ADDRESS 0x1D   //SA0=1
int accelCount[3];  // Stores the 12-bit signed value
float accelG[3];  // Stores the real accel value in g's
/* Set the scale below either 2, 4 or 8*/
const byte SCALE = 2;  // Sets full-scale range to +/-2, 4, or 8g. Used to calc real g values.
/* Set the output data rate below. Value should be between 0 and 7*/
const byte dataRate = 0;  // 0=800Hz, 1=400, 2=200, 3=100, 4=50, 5=12.5, 6=6.25, 7=1.56

byte readRegister(unsigned int8 address)
{
  byte data;
 
  i2c_Start();
  i2c_write((MMA8452_ADDRESS<<1));   // write 0xB4
  i2c_write(address);   // write register address
  i2c_Start();
  i2c_write((MMA8452_ADDRESS<<1)|0x01);   // write 0xB5
  i2c_read(TRUE);
  delay_cycles(5);
  data = i2c_read();   // Get MSB result
  i2c_stop();
 
  return data;
}
void writeRegister(unsigned char address, unsigned char data)
{
  i2c_Start();   
  i2c_write((MMA8452_ADDRESS<<1));// write 0xB4 
  i2c_write(address);   // write register address
  i2c_write(data); 
  i2c_stop();
}

void MMA8452Standby()
{
  byte c = readRegister(0x2A);
  writeRegister(0x2A, c & ~(0x01));
}
void MMA8452Active()
{
  byte c = readRegister(0x2A);
  writeRegister(0x2A, c | 0x01);
}

void initMMA8452(byte fsr, byte dataRate)
{
  MMA8452Standby();  // Must be in standby to change registers
 
  /* Set up the full scale range to 2, 4, or 8g. */
  if ((fsr==2)||(fsr==4)||(fsr==8))
    writeRegister(0x0E, fsr >> 2); 
  else
    writeRegister(0x0E, 0);
   
  /* Setup the 3 data rate bits, from 0 to 7 */
  writeRegister(0x2A, readRegister(0x2A) & ~(0x38));
  if (dataRate <= 7)
    writeRegister(0x2A, readRegister(0x2A) | (dataRate << 3)); 
   
  /* Set up portrait/landscap registers - 4 steps:
     1. Enable P/L
     2. Set the back/front angle trigger points (z-lock)
     3. Set the threshold/hysteresis angle
     4. Set the debouce rate
  // For more info check out this app note: http://cache.freescale.com/files/sensors/doc/app_note/AN4068.pdf */
  writeRegister(0x11, 0x40);  // 1. Enable P/L
  writeRegister(0x13, 0x44);  // 2. 29deg z-lock (don't think this register is actually writable)
  writeRegister(0x14, 0x84);  // 3. 45deg thresh, 14deg hyst (don't think this register is writable either)
  writeRegister(0x12, 0x50);  // 4. debounce counter at 100ms (at 800 hz)
 
  /* Set up single and double tap - 5 steps:
     1. Set up single and/or double tap detection on each axis individually.
     2. Set the threshold - minimum required acceleration to cause a tap.
     3. Set the time limit - the maximum time that a tap can be above the threshold
     4. Set the pulse latency - the minimum required time between one pulse and the next
     5. Set the second pulse window - maximum allowed time between end of latency and start of second pulse
     for more info check out this app note: http://cache.freescale.com/files/sensors/doc/app_note/AN4072.pdf */
  writeRegister(0x21, 0x7F);  // 1. enable single/double taps on all axes
  // writeRegister(0x21, 0x55);  // 1. single taps only on all axes
  // writeRegister(0x21, 0x6A);  // 1. double taps only on all axes
  writeRegister(0x23, 0x20);  // 2. x thresh at 2g, multiply the value by 0.0625g/LSB to get the threshold
  writeRegister(0x24, 0x20);  // 2. y thresh at 2g, multiply the value by 0.0625g/LSB to get the threshold
  writeRegister(0x25, 0x08);  // 2. z thresh at .5g, multiply the value by 0.0625g/LSB to get the threshold
  writeRegister(0x26, 0x30);  // 3. 30ms time limit at 800Hz odr, this is very dependent on data rate, see the app note
  writeRegister(0x27, 0xA0);  // 4. 200ms (at 800Hz odr) between taps min, this also depends on the data rate
  writeRegister(0x28, 0xFF);  // 5. 318ms (max value) between taps max
 
  /* Set up interrupt 1 and 2 */
  writeRegister(0x2C, 0x02);  // Active high, push-pull interrupts
  writeRegister(0x2D, 0x19);  // DRDY, P/L and tap ints enabled
  writeRegister(0x2E, 0x01);  // DRDY on INT1, P/L and taps on INT2
 
  MMA8452Active();  // Set to active to start reading
}

void readreg(byte address, int i, byte * dest)
{
int j;
  i2c_start(); 
  i2c_write((MMA8452_ADDRESS<<1));   // write 0xB4
  i2c_write(address);   // write register address 
  i2c_start();
  i2c_write((MMA8452_ADDRESS<<1)|0x01);   // write 0xB5
  for ( j=0; j<i; j++)
  {
    i2c_read(TRUE);
    dest[j] = i2c_read();   // Get MSB result
  }
 
  i2c_stop();
 

}

void readAccelData(int * destination)
{ int i;
  byte rawData[6];  // x/y/z accel register data stored here
  readreg(0x01, 6, &rawData[0]);  // Read the six raw data registers into data array 
  /* loop to calculate 12-bit ADC and g value for each axis */
  for ( i=0; i<6; i+=2)
  {
    destination[i/2] = ((rawData[i] << 8) | rawData[i+1]) >> 4;  // Turn the MSB and LSB into a 12-bit value
    if (rawData[i] > 0x7F)
    {  // If the number is negative, we have to make it so manually (no 12-bit data type)
      destination[i/2] = ~destination[i/2] + 1;
      destination[i/2] *= -1;  // Transform into negative 2's complement #
    }
  }
}

void main(void)
{
   int c=0;
   int i;
   lcd_init();
   start:
   output_high(PIN_A3);
    c=readRegister(0x0D);
    if(c==0x2a) printf(lcd_putc,"\fMMA8452");
    else {printf(lcd_putc,"\f not connect MMA8");goto start;}
  /* Set up the Full Scale Range to  2, 4, or 8g. (fsr,datarate)*/   
  /* Setup the 3 data rate bits, from 0 to 7 */
   initMMA8452(2,3);
 

   while(true)
   {
   
       //  printf(lcd_putc,"\nACCEL:%x",c);
     
      ////////////////////////////////////////////////////     
 
  /* If int1 goes high, all data registers have new data */
  if (input(PIN_A2)==0)  // Interrupt pin, should probably attach to interrupt function
  {
    readAccelData(accelCount);  // Read the x/y/z adc values
   
    /* Now we'll calculate the accleration value into actual g's */
    for (i=0; i<3; i++)
    {
      accelG[i] = (float) accelCount[i]/((1<<12)/(2*SCALE));  // get actual g value, this depends on scale being set
    } 
   for (i=0; i<3; i++)
    {
      printf(lcd_putc,"\nACCEL:%f",accelG[i]);
    }
   
  }

  delay_ms(100);
     
      ///////////////////////////////////////////////////


   } //while     
   
}//main


This is my new code. I read "who am i" register. But I didn't data yet.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 26, 2012 5:32 pm     Reply with quote

Quote:

readRegister()
readreg()

The two routines above are not doing a NACK on the last call to
i2c_read() in an i2c transaction. You need to fix the code so they
do that. If there is only one call to i2c_read() in a function, then it
counts as the "last" one, and it must do a NACK. Do a NACK by
giving it a 0 parameter. Example:
Code:

result = i2c_read(0);

The NACK tells the i2c slave that you are done reading data, and it's
part of the i2c specification and it's essential. Look at the diagrams on
page 17 of the MMA8452Q data sheet, for Single Byte Read and Mulitiple
Byte Read. Look at the end of each transaction for a block labeled "NAK":
http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Fri Apr 27, 2012 1:13 am     Reply with quote

data = i2c_read(); // Get MSB result
and
dest[j] = i2c_read(); // Get MSB result

lcd screen:
first line MMA8452 (this is mean = device is connect)
second line 1.573 and 52.288
but value is not changing
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 27, 2012 7:11 pm     Reply with quote

You didn't make the changes that I suggested. You didn't add the 0x00
parameter on the last call of i2c_read() in each function.

Fix the code in these two functions, and then post edited functions see I can see your changes:
Code:

readRegister()
readreg()


Also, I'm not sure if your PIC even sees the MMA8452 chip on the i2c bus.
Here is an i2c bus scanner program that will report the addresses of any
i2c slave devices that it finds on the bus. Modify the #include, #fuses,
and the #use statements so it will work with your board. Then run it
and see what devices it finds:
http://www.ccsinfo.com/forum/viewtopic.php?t=47707&start=21
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 3:18 pm     Reply with quote

Code:
int8 readRegister(unsigned int8 address)
{
  byte data;
 
  i2c_Start();
  i2c_write((MMA8452_ADDRESS<<1));   // write 0xB4
  i2c_write(address);   // write register address
  i2c_Start();
  i2c_write((MMA8452_ADDRESS<<1)|0x01);   // write 0xB5

i2c_read(0);

  delay_cycles(5);
  data = i2c_read();   // Get MSB result
  i2c_stop();
 
  return data;
}


what do you want to say?
dyeatman



Joined: 06 Sep 2003
Posts: 1933
Location: Norman, OK

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 3:59 pm     Reply with quote

Did you run PCMs bus scanner program? If so, what results did you get?
_________________
Google and Forum Search are some of your best tools!!!!
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 4:32 pm     Reply with quote

yes. I tried it. chip founds:1 ack:3a
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 4:46 pm     Reply with quote

Code:

#define  I2C_WRITE_ADDR 0x3A
#define  I2C_READ_ADDR  0x3B

int8 readreg(int8 address)
{
int8 data;
 i2c_start();                // initiate start condition
  i2c_write(I2C_WRITE_ADDR);            // device address
  i2c_write(address);            // register address
  i2c_start(); 
  i2c_write(I2C_READ_ADDR);            // device address
  data = i2c_read(0);
  i2c_stop();
return data;

}

I guess this is my code.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Apr 29, 2012 7:46 pm     Reply with quote

Quote:
yes. I tried it. chip founds:1 ack:3a

That means the i2c bus scanner program found the i2c slave chip at the
correct address. That's good.

Quote:

I guess this is my code.

#define I2C_WRITE_ADDR 0x3A
#define I2C_READ_ADDR 0x3B

int8 readreg(int8 address)
{
int8 data;
i2c_start(); // initiate start condition
i2c_write(I2C_WRITE_ADDR); // device address
i2c_write(address); // register address
i2c_start();
i2c_write(I2C_READ_ADDR); // device address
data = i2c_read(0);
i2c_stop();
return data;

}

OK, that's correct. But what about the other routine, called readreg().
Did you fix that one ?
respected



Joined: 16 May 2006
Posts: 95

View user's profile Send private message

PostPosted: Mon Apr 30, 2012 12:38 am     Reply with quote

Code:
#include <18F26J50.h>
#fuses INTRC_IO,NOPROTECT,NODEBUG,NOCPUDIV
#use delay(clock=8000000)
#include <lcdaccess.c>
#include <accel.h>
#use i2c(master, sda=PIN_B5, scl=PIN_B4)
#define  I2C_WRITE_ADDR 0x3A
#define  I2C_READ_ADDR  0x3B

int8 readreg(int8 address)
{
int8 data;
 i2c_start();                // initiate start condition
  i2c_write(I2C_WRITE_ADDR);            // device address
  i2c_write(address);            // register address
  i2c_start(); 
  i2c_write(I2C_READ_ADDR);            // device address
  data = i2c_read(0);
  i2c_stop();
return data;

}
void writeReg(unsigned char address, unsigned char data)
{
  i2c_Start();   
  i2c_write(I2C_WRITE_ADDR);// 
  i2c_write(address);   //
  i2c_write(data); 
  i2c_stop();
}
void MMA8452_Standby (void)
{
byte n;
n = readreg(CTRL_REG1);
writeReg(CTRL_REG1, n & ~ACTIVE_MASK);
}

void MMA8452_Active ()
{

writeReg(CTRL_REG1, (readreg(CTRL_REG1) | ACTIVE_MASK));
}

void main()
{
long x;
int hix,lox;
lcd_init();
int8 data;
start:
data=readreg(0x0d);

printf(lcd_putc,"\n\data: %0u", data);
if(data!=42) goto start;
MMA8452_Standby();
writeReg(CTRL_REG1,(readreg(CTRL_REG1)& ~FREAD_MASK));
MMA8452_Active();

delay_ms(100);
while(true)
{






hix=readreg(OUT_X_MSB_REG);
lox=readreg(OUT_X_LSB_REG);
x = make16(hix,lox);

printf(lcd_putc,"\fx: %0Lu",x);
delay_ms(100);
}
}


accel.h

Code:
/******************************************************************************
 *
 *      M M A 8 4 5 2 Q    A C C E L E R O M E T E R   H E A D E R
 *
 */
 #ifndef ACCEL_H
 #define ACCEL_H
 
// Accelerometer registers
#define HP_FILTER_CUTOFF                0x0f
#define CTRL_REG1         0x2a
#define CTRL_REG2         0x2b
#define CTRL_REG3         0x2c
#define CTRL_REG4         0x2d
#define CTRL_REG5         0x2e
#define XYZ_DATA_CFG                    0x0e
#define F_SETUP            0x09
#define OUTPUT_REGS         0x01
#define INT_SRC_REG         0x0c
#define PULSE_CFG         0x21
#define PULSE_SRC         0x22
#define PULSE_THS_X         0x23
#define PULSE_THS_Y         0x24
#define PULSE_THS_Z         0x25
#define PULSE_TMLT         0x26
#define PULSE_LTCY         0x27
#define PULSE_WIND         0x28
#define FF_MT_CFG         0x15
#define FF_MT_THS         0x17
#define FF_MT_COUNT         0x18
#define ASLP_COUNT         0x29
#define SYSMOD            0x0b
#define TRANS_CFG         0x1d
#define TRANS_THS         0x1f
#define TRANS_COUNT         0x20
////////////////////
#define ASLP_RATE1_MASK       0x80
#define ASLP_RATE0_MASK       0x40
#define DR2_MASK              0x20
#define DR1_MASK              0x10
#define DR0_MASK              0x08
#define LNOISE_MASK           0x04
#define FREAD_MASK            0x02
#define ACTIVE_MASK           0x01
#define ASLP_RATE_MASK        0xC0
#define DR_MASK               0x38
#define OUT_X_MSB_REG         0x01
#define OUT_X_LSB_REG         0x02
#define OUT_Y_MSB_REG         0x03
#define OUT_Y_LSB_REG         0x04
#define OUT_Z_MSB_REG         0x05
#define OUT_Z_LSB_REG         0x06

// Acceleromenet events
#define NEW_DATA_EVT                    0x01
#define ACC_SLEEP_EVT         0x02
#define CAL_PRESS_EVT         0x04
#define CAL_RELEASE_EVT         0x08

 #endif
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