LSM303 data from I2C [SOLVED]

@timb
Hi, I have been messing around with an LSM303 from Polulu (https://github.com/pololu/lsm303-arduino/tree/master/LSM303)
I have copied the .cpp and .h as well, as the serial.cpp into Spark IDE
The code seems fine as it was accepted by the IDE but I can’t seem to figure out how to read the data (x,y,z).
https://api.spark.io/v1/devices/xxxxxxxxxxxx shows it is connected but I do not know how to pull the data

any help would be awesome!
thanks!

Dup, one great way is to use Spark.publish() to put out your data. Check out the great tutorial by @bko. :smile:

1 Like

thanks peekay!
The issue is I am not familiar with I2C and so, I am wondering if the same rule applies. There is allot more code than what I am used to using analogue or digital I/O. I would like to start simple and make an api request to see that my device is talking. Hopefully that makes sense! :smile:
Thanks!

Dup, I am not sure what your situation is. Is your code running and working? If you are running the serial.ino demo than you should see some data output on your serial console (via USB). However, I would change the "snprintf" to a "sprintf". If this is not working, do you have 4.7K ohm pull-up resistors on the I2C lines?

If all this is working, then I need to understand what your trying to do! :smile:

peekay123,
thanks for your help and patience!

yes, i do have the pull-ups and I changed to "sprintf"
I guess where I am getting confused is that there are multiple ways to communicate UART, SPI and I2C which is the one I want to use. With my .cpp below, I thought I would be able to get the “report” A:x,y,z and M x,y,z

#include "application.h"
#include "LSM303.h"

LSM303 compass;

char report[80];

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
}

void loop()
{
  compass.read();

  sprintf(report, sizeof(report), "A: %6d %6d %6d    M: %6d %6d %6d",
    compass.a.x, compass.a.y, compass.a.z,
    compass.m.x, compass.m.y, compass.m.z);
  Serial.println(report);

  delay(100);
} 

Dup!

Dub, the question is whether the device is working or not over the I2C bus. I am not sure which exact Pololu LSM303 you have but the latest one works on either I2C or SPI. The examples and the library you referenced are all written for I2C.

So the first question is does anything print? To debug, you will need to add some Serial.print() lines to get an idea of what is going on. Here is your updated example to run:

include "application.h"
include "LSM303.h"
LSM303 compass;

char report[80];
bool error;

void setup()
{

	Serial.begin(9600);
	Wire.begin();
	delay(3000);				// Delay to allow for starting up Serial console
	error = compass.init()		// Returns "true" if device found
	compass.enableDefault();
}

void loop()
{
	if (error == true) {		// Returns "true" if device found
		Serial.println("LSM303 was detected");
	}
	else {
		Serial.println("Reading...");
		compass.read();

		sprintf(report, sizeof(report), "A: %6d %6d %6d M: %6d %6d %6d",
		compass.a.x, compass.a.y, compass.a.z,
		compass.m.x, compass.m.y, compass.m.z);
		Serial.println(report);
	}

	delay(1000);
}

Run the updated code and see what you get on your Serial (USB) monitor and let me know. :smile:

Hey peekay123,
I have the core talking serial but it is forcing my PC (mouse) to act strangely where I no longer have control. Not sure if it has to do with the COM#, must I use COM7 even though it is already in use?
Also, is it a big deal if I use “snprintf” rather than “sprintf” ? The code compiles with snprintf and not sprintf
Thanks!

:wink:

Dup, follow the link kennethlimcp provided to hopefully fix the mouse issue. I forgot to remove the second argument in the sprintf line like this:

sprintf(report, "A: %6d %6d %6d M: %6d %6d %6d",
		compass.a.x, compass.a.y, compass.a.z,
		compass.m.x, compass.m.y, compass.m.z);
		Serial.println(report);

You can keep using the snprintf if you wish.

So what were you getting out of the test program?

peekay123,
Thanks!

LSM303 was detected
LSM303 was detected
LSM303 was detected
LSM303 was detected
LSM303 was detected

Dup, I should really re-read my code before posting! Here is the correct code that would also print the data:

include "application.h"
include "LSM303.h"
LSM303 compass;

char report[80];
bool error;

void setup()
{

	Serial.begin(9600);
	Wire.begin();
	delay(3000);				// Delay to allow for starting up Serial console
	error = compass.init()		// Returns "true" if device found
	compass.enableDefault();
}

void loop()
{
	if (error == false) {		// Returns "false" if device NOT found
		Serial.println("LSM303 was NOT detected");
	}
	else {
		Serial.println("Reading...");
		compass.read();

		sprintf(report, sizeof(report), "A: %6d %6d %6d M: %6d %6d %6d",
		compass.a.x, compass.a.y, compass.a.z,
		compass.m.x, compass.m.y, compass.m.z);
		Serial.println(report);
	}

	delay(1000);
}

Have fun!

thanks!
I get this…pretty cool stuff

Reading…
A: 215 471 -16010 M: -2086 -2548 2199

next step is to get this stuff into a spreadsheet…thanks again!

Dup, check out this topic on logging to a Google SpreadSheet! :smile:

1 Like

peekay123,
Thanks!!
Dup

@peekay123

Hi peekay123,
I am having difficulty fetching the data into the spreadsheet. I have succeeded in bringing in single data such as temp along with timestamp however the accelerometer has multiple data points A: 215 471 -16010 M: -2086 -2548 2199 and I can’t seem to figure out how to JSON parse! :frowning:

This is what I have:

sprintf(resultstr, "{“report:A: %6d %6d %6d M: %6d %6d %6d}”); // format your data as JSON, don’t forget to escape the double quotes

Any idea?
Thanks for the help!

Dup, the data that you are producing needs to be in JSON format similar to the example on the logging topic:

sprintf(resultstr, "{\"data1\":%d,\"data2\":%d}", data1, data2);

the result of doing a GET from the spreadsheet will look like this:

"result": "{\"data1\":23,\"data2\":26,}",

The JSON structure here shows a string object called "results". This string can be parsed into parts by using the "" delimiter to get names (data1, data2) and values (23, 26). This can be parsed by the google spreadsheet using (from the example):

  var p = JSON.parse(result); // parse the JSON you created
  var d = new Date(); // time stamps are always good when taking readings
  sheet.appendRow([d, p.data1, p.data2]); // append the date, data1, data2 to the sheet

So your code should read something like this:

sprintf (resultstr, "{"Ax":%6d,"Ay":%6d,"Az":%6d,"Mx":%6d,"My":%6d,"Mx":%6d}", ax, ay, az, mx, my, mz);

Which will result in this JSON output from the Spark Cloud (where 1234 is the actual value of the variables):

"result": "{"Ax":1233,"Ay":1234,"Az":1234,"Mx":1234,"My":1234,"Mx":1234}"

Then, in the spreadsheet, you parse that out like this:

sheet.appendRow([d, p.Ax, p.Ay, p.Az, p.Mx, p.My, p.Mz]); // append the date and data to the sheet

Give that a shot and let me know how it goes. :smile:

2 Likes

Thanks peekay123!
I got it going!!
3/27/2014 13:23:54 360 290 -15901 1443 -97 1114
3/27/2014 13:26:02 333 118 -15905 1349 317 1001
3/27/2014 13:29:51 466 75 -15962 1465 139 1017
3/27/2014 13:30:50 448 73 -15941 1486 150 1022
3/27/2014 13:32:04 419 73 -15934 1480 145 1030
3/27/2014 13:32:05 419 73 -15934 1480 145 1030

For some reason I had to create a new spreadsheet and not update an existing. Now I can examine the stability of the component while sitting still along with other tests

I learned something this morning, due to the crazy snow storm in NB, my kids are on the Xbox playing Call of Duty and I think it is affecting my core wifi operation! I had issues flashing, and it appears to affect the fetching into the spreadsheet.

Thanks again!

2 Likes

Glad you guys got things working! :slight_smile:

Now that I have things working, I can see real-time data via serial USB :slight_smile: The sensor can generate data at high speeds which I would like to store and analyse.
Can I store the data on the core then “GET” or “PUBLISH” so I can get a snapshot of the data? I.e. every 5 mins the core collects data then publishes all of the collected data
Thanks!

Dup, there are a couple of challenges with this. First, Spark.publish() is limited to a string of 63 characters per call. On top of that, there is a limit on how many publish events you can have per minute. I believe using publish is not feasible here.

The second challenge is the amount of available RAM. Storing 5 minutes worth of data (assume 40 bytes) at 1 second intervals would be 300 * 40 = 1200 bytes which I suspect will push your code over the available limit.

Another way is to use the microSD library, store you data on the SD and then "POST" the data using TCPClient or "GET" the data using TCPServer. :smile:

1 Like