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 extendsSensor
).
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 theSensorErrors
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 bysample()
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, thesample()
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).
Usually every driver defines its own structure, inheriting from the basic ones. Each of these structures also define print()
andheader()
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
#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;
}