/* compass.c * * Software to read from the CMPS03 magnetic compass. * * By Josh Marshall, joshua dot marshall at studentmail dot newcastle dot edu dot au * October 15, 2004. * * Adapted from code for the SP03 speech synthesiser * By Bram Stolk, b.stolk at chello.nl * * Bram Stolk's notes: * In linux, you can do I2C stuff in user-space, if you enable * the device-interface to i2c. You can use plain read() and * write() calls on your /dev/i2c-0 file. * * NOTE: Check if you have an i2c adapter active by doing: * cat /proc/bus/i2c * If this comes up empty, then you have no adapters. If the * file does not exist at all, you probably lack i2c kernel * support alltogether. */ #include #include #include #include #include #include #include /* Note that the documentation for the compass states its address as 0xC0. * However, this includes the low bit which specifies read or write. * Linux i2c does not include this bit in this address, so the actual * address is 0xC0 shifted down, 0x60. */ #define CMPS03_ADDR 0x60 /* The important registers on the compass. Internal/test registers omitted. */ #define CMPS03_SOFTWARE_REVISION 0x0 #define CMPS03_BEARING_BYTE 0x1 #define CMPS03_BEARING_WORD_HIGH 0x2 #define CMPS03_BEARING_WORD_LOW 0x3 #define CMPS03_CALIBRATE_CMD 0xF int main(int argc, char *argv[]) { char *end; int res,file; int e1; char filename[20] ; long funcs; int heading_byte, heading_word_h, heading_word_l; int bearing_long, bearing_degrees; sprintf(filename,"/dev/i2c-0"); if ((file = open(filename,O_RDWR)) < 0) { e1 = errno; if (e1 != ENOENT) { fprintf(stderr,"Error: Could not open file '%s' : %sn", filename,strerror(e1)); if(e1 == EACCES) fprintf(stderr,"Run as root?n"); } } if (ioctl(file,I2C_FUNCS,&funcs) < 0) { fprintf(stderr, "Error: Could not get the adapter functionality maxtrix: %sn", strerror(errno)); exit(1); } if (! (funcs & I2C_FUNC_SMBUS_QUICK)) { fprintf(stderr, "Error: Can't use SMBus Quick Write command " "on this bus (ISA bus?)n"); exit(1); } fprintf(stderr, "I2C functionality: %08Xn", funcs); if (ioctl(file,I2C_SLAVE,CMPS03_ADDR) < 0) { if (errno == EBUSY) { printf("device is busyn"); } printf("Got error: %d\n", errno); exit(0); } /* Get software revision number */ res = i2c_smbus_read_byte_data(file, CMPS03_SOFTWARE_REVISION); if (res < 0) { printf("Cannot read software revision leveln"); } else { printf("Software revision level: %02xn", res); } /* Loop and read from the compass. */ while (1) { /* The heading byte is 0-255 for the 360 degrees. */ heading_byte = i2c_smbus_read_byte_data(file, CMPS03_BEARING_BYTE); if (heading_byte < 0) { printf("Error reading from compass."); exit(1);} /* The high resolution heading is given in two registers, and is 10 * the * heading in degrees, ie 359.9 degrees reads as 3599. */ heading_word_h = i2c_smbus_read_byte_data(file, CMPS03_BEARING_WORD_HIGH); if (heading_word_h < 0) { printf("Error reading from compass."); exit(1);} heading_word_l = i2c_smbus_read_byte_data(file, CMPS03_BEARING_WORD_LOW); if (heading_word_l < 0) { printf("Error reading from compass."); exit(1);} /* Combine the two bytes, and get the heading in degrees. */ bearing_long = heading_word_h * 256 + heading_word_l; bearing_degrees = bearing_long / 10; printf("Bearing: %d \n", bearing_degrees); /* Wait for a while. */ usleep(200000); } }