Compass Chip Over I2C

04 May 2010

I'm having some problems getting my mbed to read in data from a CMPS03 compass chip, and save it to a text (or other) file for later use - any help would be greatly appreciated, even if it turns out to be a simple mistake! The code I'm trying to use is below:

(The various LEDs are so I could try to visually see where the program was up to)

#include "mbed.h"

I2C compass(p9, p10);
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

LocalFileSystem local("local");

int main() {
        
        int address = 0xC0;
        char read_cmd[2], read_result[3] = {0}, prnt_result[3] = {0};
        read_cmd[0] = 2;      
        unsigned short data;

         led1 = 1;
         wait(0.5);
        
         compass.write(address, read_cmd, 1);
         wait(0.05);
         compass.read(address, read_result, 2);
         led2 = 1;
         read_result[0] = prnt_result[2];
         read_result[1] = prnt_result[1];
         read_result[2] = prnt_result[0];

         memcpy(&data, prnt_result, 3);
         led3 = 1;
        
         FILE *fp = fopen("/local/out.txt", "w");
         fprintf(fp, "Begin Compass Log...");
                 
         led4 = 1;
    
         fprintf(fp,"The compass data is: ");
         fputs(prnt_result, fp);
         fclose(fp);
         led4 = 0;
         
        }

05 May 2010

I'm planning to try something similar with a mindsensors I2C compass (CMP2X), hence the interest in this topic.

I think it might indeed be a simple mistake...

Aren't you overwriting the read_result data from your compass with prnt_result values (three lines afer the led2 = 1 statement)?

Perhaps if you swap those statements to something like this you might have better luck:

prnt_result[0] = read_result[0];

 

05 May 2010

Hi Torben,

Would it be possible for you to explain what problems you are having explicitly? Does the file not get written to or does it give a non-sensical value? What LED does the program get up to?

Some of the things I notice are:

  • After reading the contents of registers 2 and 3 into read_result[0] and read_result[1] you are then setting read_result[0] = 0 and read_result[1] = 0 due to the fact all the elements of the prnt_result array were initialised to 0. As Andrew pointed out, you'll need to swap the statements.
  • The bearing is contained as a 16-bit number in registers 2 and 3, and you only read in 2 bytes to read_result, so your read_result array only needs to contain 2 elements.
  • I believe the size of an unsigned short on the compiler is 2 bytes; I don't know what sort of behaviour memcpy'ing 3 bytes to a 2 byte location will exhibit, but I'm sure it can't be good.
  • You're memcpy'ing zeroes to the data variable as the prnt_result array holds zeroes. I assume the prnt_result array should hold the value of the bearing in "human readable" form, but at the moment it isn't doing anything because it doesn't contain the right values.
  • If you're going to use fputs to put the result into the file, then prnt_result needs to be a null-terminated string, meaning the last element of the array needs to be the null character '\0' - assuming the data variable held the correct value you could simply do: fprintf(fp, "The compass data is: %i\n", data); instead.

I have written a class for the CMPS03 which is successfully logging values to the local file system.

I hope this helps, let me know if it doesn't.

Cheers,

Aaron

05 May 2010 . Edited: 05 May 2010

Thanks for your swift responses to my somewhat amateur mistakes! I've changed the code round to eliminate the problems pointed out by you both, and then written a new program based mostly on Aaron's library, so thanks a thousandfold for that!

Cheers!