|
|
The `src/shared/sensors/Sensor.h` header file contains the base classes used to define sensors: every new sensor must inherit from one of them.
|
|
|
|
|
|
- `AbstractSensor` is the top-level virtual class.
|
|
|
- It is extended by `Sensor`.
|
|
|
- A `SensorFIFO` is also provided for driver that use a FIFO (it extends `Sensor`).
|
|
|
|
|
|
## AbstractSensor class
|
|
|
* `init()`: this is the first method to be called before using the sensor. It sets up the sensor, e.g. registers.
|
|
|
* `selfTest()`: check if the sensor is correctly working.
|
|
|
* `sample()`: this method manages the sampling and samples storage.
|
|
|
* `getLastError()`: useful to get the last error recorded by the sensor driver. A set of base errors is defined in the `SensorErrors` enum.
|
|
|
|
|
|
Both `init()` and `selfTest()` return a boolean value indicating whether the operation succeded or not.
|
|
|
|
|
|
## Sensor class
|
|
|
Each `Sensor` object has to implement the `AbstractSensor`'s `init()` and `selfTest()` methods.
|
|
|
|
|
|
Other two methods are provided:
|
|
|
* `sampleImpl()`: private method used by `sample()` to actually read data from the sensor and store it in local variables. Override this method for reading sensors' output when writing a new driver. In order to sample the sensor, the `sample()` method has to be called instead.
|
|
|
* `getLastSample()`: returns the last available sample from the driver.
|
|
|
|
|
|
`Sensor` is a template class and the template value specifies the data structure held and returned by the sensor (e.g. a `TestSensor` will extend `Sensor<TestData>`, where test data is a specific structure for this sensor).
|
|
|
|
|
|
## SensorFIFO class
|
|
|
This class extends `Sensor` and adds method to manage the FIFO:
|
|
|
* `getLastFifo()`: return the last stored FIFO.
|
|
|
* `getFifoElement(uint32_t i)`: return the i-th element of the last stored FIFO.
|
|
|
* `getLastFifoSize()`: return the number of elements in the last stored FIFO.
|
|
|
* `IRQUpdateTimestamp(uint64_t ts)`: called by the interrupt handling routine in order to provide the timestamp of the last interrupt, to accordingly update all the timestamps of the elements contained in the FIFO.
|
|
|
|
|
|
Since `SensorFIFO` inherits from `Sensor`, is also is a template class and needs the template to be the data structure used and returned by the sensor.
|
|
|
A second template parameter specifies the FIFO size, in order to statically allocate it.
|
|
|
|
|
|
## Sensor Data
|
|
|
The `src/shared/sensors/SensorData.h` file also defines some base data structures that can be used by sensors (e.g. `PressureData`, `AccelerometerData`, etc).
|
|
|
|
|
|
> :information_source: **Usually every driver defines its own structure, inheriting from the basic ones. Each of these structures also define `print()` and `header()` methods which are needed to decode log files. Moreover, the logger uses the struct name as a filename on the SD card, so every sensor has to define a different one if it needs to be logged.**
|
|
|
|
|
|
## Example
|
|
|
|
|
|
```cpp
|
|
|
#include <cmath>
|
|
|
#include "Common.h"
|
|
|
#include "sensors/Sensor.h"
|
|
|
|
|
|
using miosix::getTick;
|
|
|
using miosix::TICK_FREQ;
|
|
|
|
|
|
struct TestData : public TimestampData
|
|
|
{
|
|
|
float value;
|
|
|
|
|
|
TestData(uint64_t t, float v) : TimestampData{t}, value(v) {}
|
|
|
|
|
|
TestData() : TimestampData{0}, value(0.0f) {}
|
|
|
|
|
|
static std::string header()
|
|
|
{
|
|
|
return "timestamp,value\n";
|
|
|
}
|
|
|
|
|
|
void print(std::ostream& os) const
|
|
|
{
|
|
|
os << timestamp << "," << value << "\n";
|
|
|
}
|
|
|
};
|
|
|
|
|
|
class TestSensor : public Sensor<TestData>
|
|
|
{
|
|
|
public:
|
|
|
TestSensor() {}
|
|
|
~TestSensor() {}
|
|
|
|
|
|
bool init() override
|
|
|
{
|
|
|
// initialize the sensor here
|
|
|
// e.g. set config registers and check whoami
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool selfTest() override
|
|
|
{
|
|
|
// check that the sensor is properly working
|
|
|
// e.g. check values tolerance over a set of samples
|
|
|
// or what the datasheet suggests
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
TestData sampleImpl() override
|
|
|
{
|
|
|
// read data and store it in local variable "last_sample"
|
|
|
TRACE("[TestSensor] sampleImpl() \n");
|
|
|
return TestData(static_cast<uint64_t>(getTick()),
|
|
|
10 * sin(PI * static_cast<float>(getTick()) /
|
|
|
static_cast<float>(TICK_FREQ)));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
int main()
|
|
|
{
|
|
|
TestSensor s;
|
|
|
|
|
|
for(;;)
|
|
|
{
|
|
|
s.sample();
|
|
|
miosix::Thread::sleep(10);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
``` |
|
|
\ No newline at end of file |