I'm trying to interface a pressure sensor (MS5803-14BA) with my board (NUCLEO-STM32L073RZ).
According to the datasheet (page 3), the pressure sensor requires some milliseconds before the measurement is ready to be read. For my project, I would be interested in the highest resolution that requires around 10 ms for the conversion of the raw data.
Unfortunately, this pressure sensor doesn't have any interrupt pin that can be exploited to see when the measurement is ready, and therefore I temporarily solved the problem putting a delay after the request of new data.
I don't like my current solution, since in those 10 ms I could put the mcu working on something else (I have several other sensors attached to my board), but without any interrupt pin, I'm not sure about what is the best way to solve this problem.
Another solution came into my mind: Using a timer that triggers every say 20 ms and performs the following operations:
1.a Read the current value stored in the registers (discarding the first value)
1.b Ask for a new value
In this way, at the next iteration I would just need to read the value requested at the end of the previous iteration.
What I don't like is that my measurement would be always 20 ms old. Until the delay remains 20 ms, it should be still fine, but if I need to reduce the rate, the "age" of the reading with my solution would increase.
Do you have any other idea about how to deal with this?
Thank you.
Note: Please let me know if you would need to see my current implementation.
First of all thank you for your suggestions. I tried to analyze every single possible solution you proposed.
The solution proposed by Peter seemed very interesting but I have to say that, after having gone through the datasheet several times, I don't believe that is feasible. My consideration is based on the following facts.
Using a scope I see that the acknowledge is received right after sending the command for doing conversion. See following image concerning the temperature conversion:
It seems quite clear to me the acknowledge bit right after the command. After that the SDA line (yellow) goes high, therefore I don't see how it is possible that I can exploit that for detecting when the conversion is ready.
Concerning the solution when using SPI, yes, the SDO remains low during the conversion, but I cannot use it: I need to stick with I2C. Furthermore, I have other sensors attached to that SPI bus and I agree with what Gabriel Staples says.
After my consideration I went for the solution proposed by Gabriel Staples (considering that, in order to read pressure value, I also need to read and convert temperature).
My current solution is based on a state machine with 6 states. In my solution, I distinguish between the wait time for the pressure conversion and the wait time for the temperature conversion with the idea the I could try to see how much the pressure reading degrades if I use a less precise temperature reading.
Here is my current solution. The following function is called inside the main while:
I don't pretend that my solution is better. I just post it in order to have an opinion from you guys. Note: I'm still working on it. Therefore I cannot guarantee is bug-free!
For PeterJ_01: I could agree that this is not strictly a teaching portal, but I believe that everybody around here asks questions to learn something new or to improve theirselves. Therefore, if you believe that the solution using the ack is better, it would be great if you could show us a draft of your idea. For me it would be something new to learn.
Any further comment is appreciated.
This isn't a "how to read a sensor" problem, this is a "how to do non-blocking cooperative multi-tasking" problem. Assuming you are running bare-metal (no operating system, such as FreeRTOS), you have two good options.
First, the datasheet shows you need to wait up to 9.04 ms, or 9040 us.
Now, here are your cooperative multi-tasking options:
Send a command to tell the device to do an ADC conversion (ie: to take an analog measurement), then configure a hardware timer to interrupt you exactly 9040 us later. In your ISR you then can either set a flag to tell your main loop to send a read command to read the result, OR you can just send the read command right inside the ISR.
Use non-blocking time-stamp-based cooperative multi-tasking in your main loop. This will likely require a basic state machine. Send the conversion command, then move on, doing other things. When your time stamp indicates it's been long enough, send the read command to read the converted result from the sensor.
Number 1 above is my preferred approach for time-critical tasks. This isn't time-critical, however, and a little jitter won't make any difference, so Number 2 above is my preferred approach for general, bare-metal cooperative multi-tasking, so let's do that.
Here's a sample program to demonstrate the principle of time-stamp-based bare-metal cooperative multi-tasking for your specific case where you need to:
Code:
For another really simple timestamp-based multi-tasking example see Arduino's "Blink Without Delay" example here.
Here's an example of how to configure a timer for use as a timestamp-generator on an STM32F2 microcontroller.
This shows functions for
configureHardwareTimer()
andgetMicros()
, used above: