26#include <util/crc16.h>
37 : spiSlave(bus, cs, spiConfig), config(config)
55 uint8_t data[FULL_FRAME_SIZE] = {0};
56 sendCommand(transaction, Command::RESET, data);
64 uint16_t response = transaction.
read24() >> 8;
67 if (response != RESET_CMD_RESPONSE)
70 LOG_ERR(logger,
"Reset command failed, response was {:X}", response);
79 for (
int i = 0; i < CHANNELS_NUM; i++)
84 enableGlobalChopMode();
86 disableGlobalChopMode();
89 this->config = config;
104 applyChannelConfig(channel, calibrationConfig);
107 int32_t averageValue = 0;
108 int realSampleCount = 0;
109 for (
int i = 0; i < CALIBRATION_SAMPLES; i++)
115 int32_t rawValues[CHANNELS_NUM];
116 if (!readSamples(rawValues))
122 averageValue += rawValues[
static_cast<int>(channel)];
127 if (realSampleCount == 0)
129 LOG_ERR(logger,
"Calibration failed, no valid samples");
134 averageValue /= realSampleCount;
135 LOG_INFO(logger,
"Channel {} average offset: {}",
136 static_cast<int>(channel),
137 averageValue * getLSBSizeFromGain(calibrationConfig.pga));
140 if (averageValue != 0)
148 applyChannelConfig(channel,
163 for (
int i = 0; i < CHANNELS_NUM; i++)
165 applyChannelConfig(
static_cast<Channel>(i), selfTestConfig);
166 setChannelInput(
static_cast<Channel>(i), Input::POSITIVE_DC_TEST);
168 setOversamplingRatio(OversamplingRatio::OSR_16256);
169 disableGlobalChopMode();
172 int32_t averageValues[CHANNELS_NUM] = {0};
173 int realSampleCount = 0;
174 for (
int i = 0; i < SELF_TEST_SAMPLES; i++)
180 int32_t rawValues[CHANNELS_NUM];
181 if (!readSamples(rawValues))
187 for (
int j = 0; j < CHANNELS_NUM; j++)
188 averageValues[j] += rawValues[j];
193 if (realSampleCount == 0)
196 "Failed self test with positive DC signal, no valid samples");
202 for (
int i = 0; i < CHANNELS_NUM; i++)
205 averageValues[i] /= realSampleCount;
209 averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
212 if (volts < V_REF * TEST_SIGNAL_FACTOR - TEST_SIGNAL_SLACK)
216 "Self test failed on channel {} on positive test signal, "
223 averageValues[i] = 0;
228 for (
int i = 0; i < CHANNELS_NUM; i++)
229 setChannelInput(
static_cast<Channel>(i), Input::NEGATIVE_DC_TEST);
233 for (
int i = 0; i < SELF_TEST_SAMPLES; i++)
239 int32_t rawValues[CHANNELS_NUM];
240 if (!readSamples(rawValues))
246 for (
int j = 0; j < CHANNELS_NUM; j++)
247 averageValues[j] += rawValues[j];
252 if (realSampleCount == 0)
255 "Failed self test with positive DC signal, no valid samples");
261 for (
int i = 0; i < CHANNELS_NUM; i++)
264 averageValues[i] /= realSampleCount;
268 averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
271 if (volts > -V_REF * TEST_SIGNAL_FACTOR + TEST_SIGNAL_SLACK)
275 "Self test failed on channel {} on negative test signal, "
284 for (
int i = 0; i < CHANNELS_NUM; i++)
285 setChannelInput(
static_cast<Channel>(i), Input::DEFAULT);
297 int32_t rawValues[CHANNELS_NUM];
298 if (!readSamples(rawValues))
307 for (
int i = 0; i < CHANNELS_NUM; i++)
316void ADS131M04::applyChannelConfig(
Channel channel,
317 Config::ChannelConfig config)
321 setChannelPGA(channel, config.pga);
322 setChannelOffset(channel, config.offset);
323 setChannelGain(channel, config.gain);
324 enableChannel(channel);
328 disableChannel(channel);
334 changeRegister(Register::REG_CLOCK,
static_cast<uint16_t
>(ratio),
338void ADS131M04::setChannelPGA(
Channel channel,
PGA gain)
340 int shift =
static_cast<int>(channel) * 4;
341 changeRegister(Register::REG_GAIN,
static_cast<uint16_t
>(gain) << shift,
345void ADS131M04::setChannelOffset(
Channel channel, uint32_t offset)
359 writeRegister(getChannelOffsetRegisterMSB(channel), offset >> 8);
360 writeRegister(getChannelOffsetRegisterLSB(channel), offset << 8);
363void ADS131M04::setChannelGain(
Channel channel,
double gain)
379 uint32_t rawGain = gain * (1 << 23);
393 writeRegister(getChannelGainRegisterMSB(channel), rawGain >> 8);
394 writeRegister(getChannelGainRegisterLSB(channel), rawGain << 8);
397void ADS131M04::enableChannel(
Channel channel)
399 changeRegister(Register::REG_CLOCK, 1 << (
static_cast<int>(channel) + 8),
400 1 << (
static_cast<int>(channel) + 8));
403void ADS131M04::disableChannel(
Channel channel)
405 changeRegister(Register::REG_CLOCK, 0,
406 1 << (
static_cast<int>(channel) + 8));
409void ADS131M04::enableGlobalChopMode()
415void ADS131M04::disableGlobalChopMode()
420void ADS131M04::setChannelInput(
Channel channel,
Input input)
422 Register reg = getChannelConfigRegister(channel);
428 switch (
static_cast<int>(channel))
431 return Register::REG_CH0_CFG;
433 return Register::REG_CH1_CFG;
435 return Register::REG_CH2_CFG;
437 return Register::REG_CH3_CFG;
443 switch (
static_cast<int>(channel))
446 return Register::REG_CH0_OCAL_MSB;
448 return Register::REG_CH1_OCAL_MSB;
450 return Register::REG_CH2_OCAL_MSB;
452 return Register::REG_CH3_OCAL_MSB;
458 switch (
static_cast<int>(channel))
461 return Register::REG_CH0_OCAL_LSB;
463 return Register::REG_CH1_OCAL_LSB;
465 return Register::REG_CH2_OCAL_LSB;
467 return Register::REG_CH3_OCAL_LSB;
473 switch (
static_cast<int>(channel))
476 return Register::REG_CH0_GCAL_MSB;
478 return Register::REG_CH1_GCAL_MSB;
480 return Register::REG_CH2_GCAL_MSB;
482 return Register::REG_CH3_GCAL_MSB;
488 switch (
static_cast<int>(channel))
491 return Register::REG_CH0_GCAL_LSB;
493 return Register::REG_CH1_GCAL_LSB;
495 return Register::REG_CH2_GCAL_LSB;
497 return Register::REG_CH3_GCAL_LSB;
501bool ADS131M04::readSamples(int32_t rawValues[CHANNELS_NUM])
504 uint8_t data[FULL_FRAME_SIZE] = {0};
506 data[0] = (
static_cast<uint16_t
>(Command::NULL_CMD) & 0xff00) >> 8;
507 data[1] = (
static_cast<uint16_t
>(Command::NULL_CMD) & 0x00ff);
510 transaction.transfer(data,
sizeof(data));
514 static_cast<uint16_t
>(data[15]) << 8 |
static_cast<uint16_t
>(data[16]);
517 if (dataCrc != calculatedCrc)
520 LOG_ERR(logger,
"Failed CRC check during sensor sampling");
527 for (
int i = 0; i < CHANNELS_NUM; i++)
529 rawValues[i] =
static_cast<uint32_t
>(data[i * 3 + 3]) << 16 |
530 static_cast<uint32_t
>(data[i * 3 + 4]) << 8 |
531 static_cast<uint32_t
>(data[i * 3 + 5]);
541uint16_t ADS131M04::readRegister(
Register reg)
543 uint8_t data[3] = {0};
546 data[0] =
static_cast<uint16_t
>(Command::RREG) >> 8 |
547 static_cast<uint16_t
>(reg) >> 1;
548 data[1] =
static_cast<uint16_t
>(reg) << 7;
551 transaction.write(data,
sizeof(data));
552 transaction.read(data,
sizeof(data));
554 return data[0] << 8 | data[1];
557void ADS131M04::writeRegister(
Register reg, uint16_t data)
561 uint8_t writeCommand[6] = {0};
564 writeCommand[0] =
static_cast<uint16_t
>(Command::WREG) >> 8 |
565 static_cast<uint16_t
>(reg) >> 1;
566 writeCommand[1] =
static_cast<uint16_t
>(reg) << 7;
567 writeCommand[3] = data >> 8;
568 writeCommand[4] = data;
571 transaction.write(writeCommand,
sizeof(writeCommand));
574 uint16_t response = transaction.read24() >> 8;
575 if (response != (WRITE_CMD_RESPONSE | (
static_cast<uint16_t
>(reg) << 7)))
578 LOG_ERR(logger,
"Write command failed, response was {:X}", response);
582void ADS131M04::changeRegister(
Register reg, uint16_t newValue, uint16_t mask)
585 uint16_t regValue = readRegister(reg);
591 regValue |= newValue;
594 writeRegister(reg, regValue);
598 uint8_t data[FULL_FRAME_SIZE])
605 data[0] = (
static_cast<uint16_t
>(command) & 0xff00) >> 8;
606 data[1] = (
static_cast<uint16_t
>(command) & 0x00ff);
608 transaction.
write(data, FULL_FRAME_SIZE);
611float ADS131M04::getLSBSizeFromGain(
PGA gain)
#define LOG_INFO(logger,...)
#define LOG_ERR(logger,...)
bool init() override
Initialize the sensor.
ADS131M04Data sampleImpl() override
Read a data sample from the sensor. In case of errors, the method should return the last available co...
bool selfTest() override
The self test samples internally connects each channel to known test signals and verifies if the samp...
void calibrateOffset(ADS131M04Defs::Channel channel)
Samples each channel, averages the samples and applies offset compensation in the device.
ADS131M04(SPIBusInterface &bus, miosix::GpioPin cs, SPIBusConfig spiConfig, const Config &config)
void applyConfig(Config config)
Overwrites the sensor settings.
Interface for low level access of a SPI bus as a master.
Provides high-level access to the SPI Bus for a single transaction.
void write(uint8_t data)
Writes a single byte to the bus.
virtual uint32_t read24()
Reads 24 bits from the bus.
constexpr uint16_t CFG_MUX
constexpr uint16_t PGA_GAIN_0
constexpr float PGA_LSB_SIZE[8]
OversamplingRatio
ADC's oversampling ratio configurations.
const auto crc16
CRC-16/CCITT-FALSE.
@ MODE_1
CPOL = 1, CPHA = 0 -> Clock high when idle, sample on first edge.
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.
bool globalChopModeEnabled
ChannelConfig channelsConfig[ADS131M04Defs::CHANNELS_NUM]
ADS131M04Defs::OversamplingRatio oversamplingRatio
SPI Bus configuration for a specific slave.
SPI::Mode mode
MSBit or LSBit first.