I have a BMP180, SD Card and MPU6050 hooked up to a Teensy LC. The intent is to make a high frequency (approximately 50 Hz, 20 ms) datalogger. The problem I am encountering is the data retrieval from the registers of the BMP180 is taking incredibly long. This was all measured using the "millis()" function.
MPU6050: Readings take approximately 1 ms in total (negligible)
BMP180: Temperature Readings take 6 ms
BMP180: Pressure Readings take 33 ms
SD Card: Data logging takes 10 ms per cycle.
The pressure readings seem to be the main culprit to the low frequency data logging that I am encountering (approximately 20 Hz). I am unsure whether the structure of the code is the root of the problem, or if my pressure sensor is faulty (bought it off Amazon).
My main inquiry is finding out how to reduce that pressure sensor latency.
In the bmp.begin() function, I passed the parameter "ULTRALOWPOWER" and it reduced the latency for the pressure reading from 33ms to 12 ms, a tremendous improvement.
First off, thank you very much for your valuable advice as it has definitely worked.
I had a couple of follow up questions however:
The delay in the datasheet for the selected mode says 4.5 ms. Is there any method to reduce the latency to that level?
Are the accuracies of the modes in the datasheet accurate? (In meters and hPa)?
Is it possible to decrease the temperature reading latency?
I read somewhere online that increasing the clock rate of the I2C Communication from 100 kHz to 400 kHz may somewhat aid in the situation. Is this a likely possibility?
It's hard to guess exactly where the extra milliseconds are going to. You should first rule out any possibility that your own code is doing it. So try it with an absolute minimum sketch first, and work from there.
Temperature reading latency shouldn't matter, unless you are forced to combine temp and pressure readings together (I'm not familiar with the device or library...). I realize that you are trying to maintain the 20Hz update rate, but consider that the temperature can not change that fast. So you will be logging a lot of redundant information. That is something that you should look at, in itself. But if you are forced to combine log records, you could sample temperature only, say, every second. Then buffer it and use the same value for 20 readings. If you do that, you might as well also average them.
Again, I am too busy to look at details myself, but possibly this would free up some processor time, since then most of the time it would only be requesting pressure readings from the device.
It is certainly worth looking into I2C bus rates, it may or may not yield anything but it's worth a try.
Your question 2 is a question for the legal department.
For the record, I assume this is what you ended up with?
bool begin(BMP085_ULTRALOWPOWER, TeensyWire);
where TeensyWire is whatever Wire instance the Teensy uses, or just
That certainly raises a valid point of the need to record temperature every cycle. I might as well just record once every second or so as temperature will not change that drastically in the time frame I am dealing with (5-10 seconds).
I will try adjusting the rate of the I2C and see if it speeds up the cycle.
The solution that I found in the end was simply adding the required mode in the parameters of the bmp.begin() function, with the "bmp" being the object created from the Adafruit library (I believe that is the correct terminology).
SPI is a potential solution to increasing cycle speed. However, since I have already created a PCB for this application, it is not possible. This may be a feasible solution in future iterations though.
I managed to reduce the pressure reading latency from 33 ms to around 12. This was done by simply passing the parameter "BMP085_ULTRALOWPOWER" (or any other mode), through the function.
bmp.begin(BMP085_ULTRALOWPOWER);
This reduces the accuracy of the reading, but by a very slight amount.
I reduced the frequency of the temperature reading. Instead of taking a temperature reading every cycle, I added an "if" statement that would record data, only on the 50th cycle. This was acceptable for my application, since the temperature does not change significantly.
if(d % 50 = 0){
}
The "d" variable was the increment variable for the "while" loop. I was having trouble with global and local variables and whatnot, but I have managed to solve the issue (let me know if further details are wanted.
The frequency of I2C communication is increased. The normal I2C frequency is 400 kHz, but this can be increased by using the "Wire.setClock()" function:
Wire.setClock(1000000);
I cannot tell if there is a difference between passing "1000000" or "1000000L". (some say to add the L, some don't and some say to add the UL, I have very little idea here)
In addition, I reorganized the structure of my code in such a manner that the SD card file is only opened once, and closed once. This is in contrast to the former set up, where the SD Card was opened and closed with every loop cycle. This shaved off approximately 10 ms from my reading latency.
In summary, I
Set the BMP180 mode
Stopped taking unnecessary temperature measurements
Increased Clock speed (400 kHz to 1 MHz)
Restructured code to only open SD Card once
This reduced the latency for the data logging from 50 ms (20 Hz), to approximately 20 ms (50 Hz). Thank you once again to @anon57585045 and @Idahowalker for the suggestions.