Electronic – Adding High Byte and Low Byte of LSM303DLHC Accelerometer Output

accelerometeri2cmicrocontrollerpic

Interpreting LSM303DLHC Accelerometer Output

Hi all,
This is my first StackExchange question ever, so I will do my best to be specific and offer as much reference as possible. I'm currently working on a navigation module which uses a PIC16F873A microcontroller to read data from a GPS via the USART module and from a LSM303DLHC Magnetometer/Accelerometer using I2C. At this stage of the project, I'm only trying to use accelerometer data, which I currently do by running the PIC in master mode and reading from the appropriate registers. The way the accelerometer works is the X,Y and Z acceleration data are stored in six different consecutive registers inside of the linear accelerometer register area (i.e. OUT_X_L_A (28h), OUT_X_H_A (29h) … OUT_Y_L_A (2Ah), OUT_Y_H_A (2Bh) … OUT_Z_L_A (2Ch), OUT_Z_H_A (2Dh)). My I2C_Accelrometer_Data(unsigned char reg_address, unsigned char ack) function reads in one byte of data at a time so my code will read the low byte and then the high byte from the next register, store them in an array of unsigned chars and add them together. According to the datasheet: LSM303DLHC these bytes are expressed in two's complement form.


A section of my C code (XC8 compiler), which I've partly adapted from here on page #6 handles it as follows:

    unsigned char ACC_Data[6];

                                            ACC_Data[0] = I2C_Accelerometer_Data(0x28, 0);//X_Low Byte
                                            ACC_Data[1] = I2C_Accelerometer_Data(0x29, 0);//X_High_Byte

                                            ACC_Data[2] = I2C_Accelerometer_Data(0x2A, 0);//Y_Low_Byte
                                            ACC_Data[3] = I2C_Accelerometer_Data(0x2B, 0);//Y_High_Byte

                                            ACC_Data[4] = I2C_Accelerometer_Data(0x2C, 0);//Z_Low_Byte
                                            ACC_Data[5] = I2C_Accelerometer_Data(0x2D, 1);//Z_High_Byte

                                            int Ax = (int) (ACC_Data[1] << 8) + ACC_Data[0];
                                            int Ay = (int) (ACC_Data[3] << 8) + ACC_Data[2];
                                            int Az = (int) (ACC_Data[5] << 8) + ACC_Data[4];

                                            char Ax_str[];
                                            char Ay_str[];
                                            char Az_str[];
                                            itoa(Ax_str, Ax, 10);
                                            lcdcmd(0x94);//third row, first column position
                                            send_string(Ax_str);

                                            itoa(Ay_str, Ay, 10);
                                            lcdcmd(0x9E);//third row, 10th column position
                                            send_string(Ay_str);

                                            itoa(Az_str, Az, 10);
                                            lcdcmd(0xD4);//4th row, first column position
                                            send_string(Az_str);

My question is: because the numbers are in two's complement binary, won't that mess up the way they are added especially since the bytes are being stored as unsigned chars? Or can I do simply what I have done above to convert these two bytes to an int? Basically, the goal to get these numbers onto an LCD screen by then converting this integer into the appropriate string, I'm just not sure if I'm using the data correctly here. Thanks in advance for any insight.

Best Answer

You are sticking the bytes together in the wrong order. since ACC_Data[0] is the low byte, and ACC_Data[1] is the high byte, you need to shift ACC_Data[1] left by 8, and add it to ACC_Data[0] (unshifted) to get the correct int value.