Publishing directly to sensors from component (hub) loop. Appears to be aorund 4000sps. DC stable, but AC still fluctuating a lot. 20ms sample time. Will try loop sampling instead of ISR sampling next.

This commit is contained in:
Chris Stuurman 2026-05-03 00:06:23 +02:00
parent 477f05a524
commit d69d0b5dfb
6 changed files with 181 additions and 182 deletions

View File

@ -114,11 +114,11 @@ void ADS131M08Hub::dump_config() {
}
uint8_t ADS131M08Hub::update_adc_word_length() {
int word_nbytes = this->adc_word_length_ >> 3;
spiframe frame(2 * word_nbytes, 0); // prepare with CMD_NULL; always cater for crc
write_array(frame); // write CMD_NULL to ADC to retrieve status
read_array(frame);
uint16_t status = frame[0] << 8 | frame[1];
setup_frame(rx_frame, 2);
transfer_array(rx_frame); // write CMD_NULL to ADC to retrieve status
zero_fill(rx_frame);
transfer_array(rx_frame);
uint16_t status = rx_frame[0] << 8 | rx_frame[1];
// print_command_response_to_string(CMD_NULL, frame).c_str();
return update_adc_word_length(status);
}
@ -261,41 +261,49 @@ void ADS131M08Hub::loop()
// Check the semaphore (0 timeout means non-blocking)
//if (xSemaphoreTake(data_ready_semhandle, 0) == pdTRUE) {
if (this->adc_init_ == 0) {
uint32_t num_samples = 0;
uint32_t crc_errors = 0;
uint32_t iterations = 0;
uint32_t not_ready = 0;
float num_samples = 0;
float crc_errors = 0;
float iterations = 0;
float not_ready = 0;
float sps = 0;
{
CHIP_SELECTx
// Perform the read here safely outside of ISR
uint64_t start = micros();
// this->txf_init(); // implementing datasheet recommended TXF init in ISR
this->adc_sync();
this->txf_init(); // implementing datasheet recommended TXF init
//this->adc_sync();
if (rms_calc_req_) {
uint16_str result = read_multi();
float_str result = read_multi();
num_samples = result[0];
crc_errors = result[1];
iterations = result[2];
not_ready = result[3];
sps = result[4];
uint64_t end = micros();
update_averages(SAMPLE_TIME_SENSOR, 1, static_cast<float>(end - start) / 1000.0);
update_averages(MAX_SAMPLES_SENSOR, 1, static_cast<float>(num_samples));
update_averages(CRC_ERRORS_SENSOR, 1, static_cast<float>(crc_errors));
uint16_t ctr = isr_ctr_;
update_averages(ISR_COUNT_SENSOR, 1, static_cast<float>(ctr));
update_averages(ITERATIONS_SENSOR, 1, static_cast<float>(iterations));
update_averages(NOT_READY_SENSOR, 1, static_cast<float>(not_ready));
// if(this->sensors_ac[SAMPLE_TIME_SENSOR] != nullptr)
// this->sensors_ac[SAMPLE_TIME_SENSOR]->publish_state(static_cast<float>(end - start)/1000.0);
// if(this->sensors_ac[MAX_SAMPLES_SENSOR] != nullptr)
// this->sensors_ac[MAX_SAMPLES_SENSOR]->publish_state(static_cast<float>(num_samples));
// if(this->sensors_ac[CRC_ERRORS_SENSOR] != nullptr)
// this->sensors_ac[CRC_ERRORS_SENSOR]->publish_state(static_cast<float>(crc_errors));
// if(this->sensors_ac[ISR_COUNT_SENSOR] != nullptr) {
//update_averages(SAMPLE_TIME_SENSOR, 1, static_cast<float>(end - start) / 1000.0);
//update_averages(MAX_SAMPLES_SENSOR, 1, static_cast<float>(num_samples));
//update_averages(CRC_ERRORS_SENSOR, 1, static_cast<float>(crc_errors));
//uint16_t ctr = isr_ctr_;
// this->sensors_ac[ISR_COUNT_SENSOR]->publish_state(static_cast<float>(ctr));
// }
//update_averages(ISR_COUNT_SENSOR, 1, static_cast<float>(ctr));
//update_averages(ITERATIONS_SENSOR, 1, static_cast<float>(iterations));
//update_averages(NOT_READY_SENSOR, 1, static_cast<float>(not_ready));
if(this->sensors_dc[SAMPLE_TIME_SENSOR] != nullptr)
this->sensors_dc[SAMPLE_TIME_SENSOR]->publish_state((end - start)/1000.0);
if(this->sensors_dc[MAX_SAMPLES_SENSOR] != nullptr)
this->sensors_dc[MAX_SAMPLES_SENSOR]->publish_state(num_samples);
if(this->sensors_dc[CRC_ERRORS_SENSOR] != nullptr)
this->sensors_dc[CRC_ERRORS_SENSOR]->publish_state(crc_errors);
if(this->sensors_dc[ISR_COUNT_SENSOR] != nullptr) {
uint16_t ctr = isr_ctr_;
this->sensors_dc[ISR_COUNT_SENSOR]->publish_state(ctr);
}
if(this->sensors_dc[ITERATIONS_SENSOR] != nullptr)
this->sensors_dc[ITERATIONS_SENSOR]->publish_state(iterations);
if(this->sensors_dc[NOT_READY_SENSOR] != nullptr)
this->sensors_dc[NOT_READY_SENSOR]->publish_state(not_ready);
if(this->sensors_dc[SPS_SENSOR] != nullptr)
this->sensors_dc[SPS_SENSOR]->publish_state(sps);
} else {
read_single();
}
@ -468,23 +476,17 @@ void ADS131M08Hub::adc_sync() {
// ********************** from datasheet ************************
void ADS131M08Hub::txf_init() {
CHIP_SELECT
setup_frame(rx_frame, numFrameWords);
if (firstRead) {
// Clear the ADC's 2-deep FIFO on the first read
for (int i = 0; i < numFrameWords * adc_word_length_; i++) {
this->write_byte(0);
}
for (int i = 0; i < numFrameWords; i++) {
this->read_byte(); // should perhaps read dwords instead of bytes, but we just want to clear the FIFO so it
// doesn't matter much?
}
this->transfer_array(rx_frame);
zero_fill(rx_frame);
this->transfer_array(rx_frame);
firstRead = false; // Clear the flag
// we will do this later, after sorting out basic communication
// DMA.enable(); // Let the DMA start sending ADC data to memory
}
// Send the dummy data to the ADC to get the ADC data
for (int i = 0; i < numFrameWords * adc_word_length_; i++) {
this->write_byte(0);
}
// Send the nulls to the ADC to get the current ADC data
zero_fill(rx_frame);
this->transfer_array(rx_frame);
}
bool ADS131M08Hub::adc_reset_retry() {
@ -518,36 +520,34 @@ bool ADS131M08Hub::adc_soft_reset() {
uint16_t reset_response;
uint16_t cmd = 0;
update_adc_word_length();
size_t word_nbytes = adc_word_length_ >> 3;
int framelength = numFrameWords * word_nbytes;
spiframe frame(framelength, 0);
auto framelength = numFrameWords * (adc_word_length_ >> 3);
size_t frame_len;
// curly braces confine chip select scope
{
CHIP_SELECTx cmd = CMD_RESET;
set_frame_word(frame, 0, cmd);
frame.resize(2 * word_nbytes);
frame_len = add_crc(frame);
frame.resize(framelength);
setup_frame(rx_frame, 2);
set_frame_word(rx_frame, 0, cmd);
frame_len = add_crc(rx_frame);
rx_frame.resize(framelength);
index += frame_len;
for (; index < framelength; index++) {
frame[index] = 0;
rx_frame[index] = 0;
}
write_array(frame);
ESP_LOGVV(TAG, "Sent Frame: %s", frame_to_string(frame).c_str());
ESP_LOGVV(TAG, "Sent Frame: %s", frame_to_string(rx_frame).c_str());
transfer_array(rx_frame);
}
delay_microseconds_safe(T_REGACQ);
update_adc_word_length(WLENGTH_24_BITS); // should be 24 after reset
word_nbytes = adc_word_length_ >> 3;
frame.resize(numFrameWords * word_nbytes);
setup_frame(rx_frame, numFrameWords);
{
CHIP_SELECTx read_array(frame);
reset_response = get_unsigned_frame_word(frame, 0, true);
bool crc_ok = check_crc(frame);
ESP_LOGVV(TAG, "Read Frame: %s CRC: %s", frame_to_string(frame).c_str(), (crc_ok ? "OK" : "FAIL"));
CHIP_SELECTx
transfer_array(rx_frame);
reset_response = get_unsigned_frame_word(rx_frame, 0, true);
bool crc_ok = check_crc(rx_frame);
ESP_LOGVV(TAG, "Read Frame: %s CRC: %s", frame_to_string(rx_frame).c_str(), (crc_ok ? "OK" : "FAIL"));
}
bool result = reset_response == RSP_RESET_OK;
ESP_LOGVV(TAG, "Reset response: [0x%04X] %s", reset_response, (result ? "OK" : "FAIL"));
ESP_LOGV(TAG, "Reset response: [0x%04X] %s", reset_response, (result ? "OK" : "FAIL"));
return result;
}
@ -625,27 +625,9 @@ uint16_t ADS131M08Hub::crc(uint16_t crc_register, uint8_t data) {
return crc_result;
}
void ADS131M08Hub::write_byte(uint8_t byte) {
void ADS131M08Hub::transfer_array(spiframe &frame) {
CHIP_SELECT
this->transfer_byte(byte);
}
uint8_t ADS131M08Hub::read_byte() {
CHIP_SELECT
uint8_t result = this->transfer_byte(0x00); // Send dummy byte to read data
return result;
}
void ADS131M08Hub::read_array(spiframe &frame) {
CHIP_SELECT
this->transfer_array(frame.data(), frame.size());
}
void ADS131M08Hub::write_array(const spiframe &frame) {
CHIP_SELECT
for (size_t i = 0; i < frame.size(); i++) {
this->transfer_byte(frame[i]);
}
Base::transfer_array(frame.data(), (size_t)frame.size());
}
//void ADS131M08Hub::transfer_array(const spiframe &tx_frame, spiframe &rx_frame) {
@ -667,24 +649,23 @@ bool ADS131M08Hub::set_measure_rms(uint8_t channel, bool enable) {
}
void ADS131M08Hub::read_single() {
int word_nbytes = adc_word_length_ >> 3;
int frame_length = numFrameWords * word_nbytes;
spiframe frame(frame_length, 0);
this->read_array(frame);
bool crc_ok = check_crc(frame);
uint16_t drdy_status = get_unsigned_frame_word(frame, 0, true) & MASK_STATUS_DRDY;
setup_frame(rx_frame, numFrameWords);
this->transfer_array(rx_frame);
bool crc_ok = check_crc(rx_frame);
uint16_t drdy_status = get_unsigned_frame_word(rx_frame, 0, true) & MASK_STATUS_DRDY;
// data_ready = crc_ok && (drdy_status != 0);
if (crc_ok) {
// sample channels
for (int i = 0; i < ADC_CHANNELS; i++) {
bool channel_ready = drdy_status & 1;
drdy_status = drdy_status >> 1;
bool ac_sensor_exist = this->sensors_ac[i] != nullptr;
bool dc_sensor_exist = this->sensors_dc[i] != nullptr;
if (channel_ready && (ac_sensor_exist || dc_sensor_exist)) {
int32_t raw = get_sign_ext_frame_word(frame, i + 1);
if (channel_ready) {
int32_t raw = get_sign_ext_frame_word(rx_frame, i + 1);
float value = this->conversion_factor_ * raw;
this->sampled_values_[i] = value;
bool ac_sensor_exist = this->sensors_ac[i] != nullptr;
bool dc_sensor_exist = this->sensors_dc[i] != nullptr;
if (ac_sensor_exist || dc_sensor_exist) {
if (ac_sensor_exist)
this->sensors_ac[i]->publish_state(value);
if (dc_sensor_exist)
@ -693,6 +674,7 @@ void ADS131M08Hub::read_single() {
}
}
}
}
// do not like what the following procedure does at all (it blocks for +-40ms), but at the moment do not know how to get
// DRDY interrupt / ISR / loop setup to respond fast enough to read multiple frames with no or the minimum possible
@ -700,13 +682,13 @@ void ADS131M08Hub::read_single() {
// hopefully reliably calculate RMS value, phase offsets, etc. the best the read_multi procedure does is to read about
// 66x 16bit / 33x 32bit word frames in 40ms which is far from ideal Once we ge the ISR and loop setup to respond fast
// enough, the following procedure should be completely re-designed
uint16_str ADS131M08Hub::read_multi() {
float_str ADS131M08Hub::read_multi() {
int32_t raw;
float value;
uint16_str result(4, 0);
float_str result(5, 0.0);
bool crc_ok, data_ready, ac_sensor_exist, dc_sensor_exist;
uint16_t drdy_status, status;
int i, iteration = 0; // going above 255 will result in overflows
int i, iteration = 0;
uint32_t elapsed_time = 0;
uint32_t loop_start_time = micros();
int word_nbytes = adc_word_length_ >> 3;
@ -722,10 +704,10 @@ uint16_str ADS131M08Hub::read_multi() {
sample_squared_sum_[i] = 0;
}
while (elapsed_time < this->sample_time_ && iteration++ < 1000) {
while ((elapsed_time < this->sample_time_) && (iteration++ < 1000)) {
result[2] = iteration;
std::fill(rx_frame.begin(), rx_frame.end(), 0);
this->read_array(rx_frame);
setup_frame(rx_frame, numFrameWords);
this->transfer_array(rx_frame);
//ESP_LOGD(TAG, "frame: %s", frame_to_string(rx_frame).c_str());
//ESP_LOGD(TAG, "iteration: %d, frame: %s", iteration, frame_to_string(rx_frame).c_str());
//ESP_LOGD(TAG, "frame_word%d: %s", 0, frame_words_to_string(rx_frame, 0, 1).c_str());
@ -743,22 +725,24 @@ uint16_str ADS131M08Hub::read_multi() {
for (i = 0; i < ADC_CHANNELS && drdy_status != 0; i++) {
data_ready = drdy_status & 1;
drdy_status = drdy_status >> 1;
if (data_ready) {
this->sampled_values_[i] = value;
ac_sensor_exist = this->sensors_ac[i] != nullptr;
dc_sensor_exist = this->sensors_dc[i] != nullptr;
if (data_ready && (ac_sensor_exist || dc_sensor_exist)) {
if (ac_sensor_exist || dc_sensor_exist) {
raw = get_sign_ext_frame_word(rx_frame, i + 1);
value = this->conversion_factor_ * raw;
this->sampled_values_[i] = value;
if (this->rms_enabled_[i]) {
(this->num_samples_[i])++;
(this->sample_sum_[i]) += value;
(this->sample_squared_sum_[i]) += value * value;
} else {
// if(ac_sensor_exist)
// this->sensors_ac[i]->publish_state(value);
// if(dc_sensor_exist)
// this->sensors_dc[i]->publish_state(value);
update_averages(i, value, value);
if(ac_sensor_exist)
this->sensors_ac[i]->publish_state(value);
if(dc_sensor_exist)
this->sensors_dc[i]->publish_state(value);
//update_averages(i, value, value);
}
}
}
}
@ -781,11 +765,11 @@ uint16_str ADS131M08Hub::read_multi() {
if (num_samples == 0) {
// should not happen, but let's play safe and avoid dividing by zero
// ESP_LOGW(TAG, "Num samples: %d", num_samples);
update_averages(i, NAN, NAN);
// if(ac_sensor_exist)
// this->sensors_ac[i]->publish_state(NAN);
// if(dc_sensor_exist)
// this->sensors_dc[i]->publish_state(NAN);
//update_averages(i, NAN, NAN);
if(ac_sensor_exist)
this->sensors_ac[i]->publish_state(NAN);
if(dc_sensor_exist)
this->sensors_dc[i]->publish_state(NAN);
} else {
float sample_sum = sample_sum_[i];
float rms_dc = sample_sum / num_samples;
@ -794,16 +778,22 @@ uint16_str ADS131M08Hub::read_multi() {
if (rms_ac_squared > 0) {
rms_ac = std::sqrtf(rms_ac_squared);
}
this->sps_ = (1e6 * (float) num_samples) / elapsed_time;
update_averages(i, rms_ac, rms_dc);
if(ac_sensor_exist)
this->sensors_ac[i]->publish_state(rms_ac);
if(dc_sensor_exist)
this->sensors_dc[i]->publish_state(rms_dc);
//update_averages(i, rms_ac, rms_dc);
}
this->num_samples_[i] = 0;
this->sample_sum_[i] = 0.0f;
this->sample_squared_sum_[i] = 0.0f;
}
}
this->sps_ = (1e6 * (float) result[0]) / elapsed_time;
result[4] = this->sps_;
return result;
}
/*
/// @brief Updates rolling averages for rms_ac and rms_dc. Window = 2
/// @param channel
/// @param rms_ac
@ -897,20 +887,20 @@ float ADS131M08Hub::get_average(uint8_t channel, bool read_ac) {
}
return result;
}
*/
bool ADS131M08Hub::adc_lock(bool enable) {
int word_nbytes = adc_word_length_ >> 3;
spiframe frame(word_nbytes * 2, 0);
setup_frame(rx_frame, 2);
uint16_t command = CMD_UNLOCK;
if (enable) {
command = CMD_LOCK;
}
set_frame_word(frame, 0, command);
add_crc(frame);
write_array(frame);
set_frame_word(rx_frame, 0, command);
add_crc(rx_frame);
transfer_array(rx_frame);
delay_microseconds_safe(T_REGACQ);
read_array(frame);
auto ack = get_unsigned_frame_word(frame, 0, true);
zero_fill(rx_frame);
transfer_array(rx_frame);
auto ack = get_unsigned_frame_word(rx_frame, 0, true);
return ack == command;
}
@ -981,27 +971,26 @@ bool ADS131M08Hub::adc_register_write(uint16_t start_address, const uint16_str &
if (nregs == 0) {
return false; // invalid
}
int word_nbytes = adc_word_length_ >> 3;
int wreg_framelength = word_nbytes * (2 + nregs); // ensure room for crc
int rreg_resp_framelength = word_nbytes * (2 + (nregs == 1 ? -1 : nregs)); // add room for CRC if nregs > 1
//spiframe frame(wreg_framelength, 0);
//spiframe rxframe(wreg_framelength, 0);
int wreg_nwords = 2 + nregs; // ensure room for crc
int rreg_resp_framelength = 2 + (nregs == 1 ? -1 : nregs); // add room for CRC if nregs > 1
//spiframe frame(wreg_nwords, 0);
//spiframe rxframe(wreg_nwords, 0);
uint16_t addr_regcnt_mask = (start_address << 7) | ((nregs - 1) & MASK_CMD_RW_REG_COUNT);
uint16_t wreg_addr_opcode = CMD_WREG | addr_regcnt_mask; // Combine WREG command, start_address and register count
uint16_t rreg_addr_opcode = CMD_RREG | addr_regcnt_mask; // Combine RREG command, start_address and register count
bool has_mode_reg =
(start_address == REG_MODE) || ((start_address < REG_MODE) && ((start_address + nregs) > REG_MODE));
tx_frame.resize(wreg_framelength);
rx_frame.resize(wreg_framelength);
setup_frame(rx_frame, wreg_nwords);
{
CHIP_SELECT set_frame_word(tx_frame, 0, wreg_addr_opcode);
CHIP_SELECT
set_frame_word(rx_frame, 0, wreg_addr_opcode);
for (int i = 0; i < nregs; i++) {
set_frame_word(tx_frame, i + 1, data[i]);
set_frame_word(rx_frame, i + 1, data[i]);
}
add_crc(tx_frame);
//ESP_LOGD(TAG, "%s\n", rwreg_command_frame_to_string(tx_frame).c_str());
//ESP_LOGD(TAG, "Send Frame: %s", frame_to_string(tx_frame).c_str());
transfer_array(tx_frame.data(), tx_frame.size()); // WREG
add_crc(rx_frame);
//ESP_LOGD(TAG, "%s\n", rwreg_command_frame_to_string(rx_frame).c_str());
//ESP_LOGD(TAG, "Send Frame: %s", frame_to_string(rx_frame).c_str());
transfer_array(rx_frame); // WREG
}
if (has_mode_reg) {
update_adc_word_length();
@ -1032,31 +1021,29 @@ uint16_str ADS131M08Hub::adc_register_read(uint8_t address, uint8_t nregs) {
ESP_LOGE(TAG, "Trying to read %d registers. This exceeds maximum register read count of %d!", nregs, MAX_FRAME_SIZE - 2);
return result; // invalid
}
int word_nbytes = adc_word_length_ >> 3;
int request_framelength = 2 * word_nbytes; // ensure room for crc
int response_framelength = word_nbytes * (2 + (nregs == 1 ? -1 : nregs)); // add room for CRC if nregs > 1
spiframe frame(response_framelength, 0);
int rreg_nwords = 2; // ensure room for crc
int response_nwords = 2 + (nregs == 1 ? -1 : nregs); // add room for CRC if nregs > 1
uint16_t rreg_addr_opcode =
CMD_RREG | (address << 7) |
((nregs - 1) & MASK_CMD_RW_REG_COUNT); // Combine RREG command, address and register count
{
CHIP_SELECT
frame.resize(request_framelength);
set_frame_word(frame, 0, rreg_addr_opcode);
add_crc(frame);
write_array(frame); // send RREG
setup_frame(rx_frame, rreg_nwords);
set_frame_word(rx_frame, 0, rreg_addr_opcode);
add_crc(rx_frame);
transfer_array(rx_frame); // send RREG
}
ESP_LOGVV(TAG, "%s\n", rwreg_command_frame_to_string(frame).c_str());
ESP_LOGVV(TAG, "Sent Frame: %s", frame_to_string(frame).c_str());
ESP_LOGVV(TAG, "%s\n", rwreg_command_frame_to_string(rx_frame).c_str());
ESP_LOGVV(TAG, "Sent Frame: %s", frame_to_string(rx_frame).c_str());
delay_microseconds_safe(T_REGACQ);
{
CHIP_SELECT
frame.resize(response_framelength);
read_array(frame);
setup_frame(rx_frame, response_nwords);
transfer_array(rx_frame);
}
ESP_LOGVV(TAG, "Recv Frame: %s", frame_to_string(frame).c_str());
ESP_LOGVV(TAG, "Recv Frame: %s", frame_to_string(rx_frame).c_str());
if (nregs > 1) {
bool crc_ok = check_crc(frame);
bool crc_ok = check_crc(rx_frame);
if (!crc_ok) {
ESP_LOGW(TAG, "CRC failed reading ADC registers!");
result.clear();
@ -1069,15 +1056,15 @@ uint16_str ADS131M08Hub::adc_register_read(uint8_t address, uint8_t nregs) {
// pretend this is the ack
if (nregs > 1) {
offset = 1;
rreg_ack = get_unsigned_frame_word(frame, 0, true);
rreg_ack = get_unsigned_frame_word(rx_frame, 0, true);
}
// uint16_t rreg_ack = (nregs == 1) ? rreg_addr_opcode : get_unsigned_frame_word(frame, 0, true);
// uint16_t rreg_ack = (nregs == 1) ? rreg_addr_opcode : get_unsigned_frame_word(rx_frame, 0, true);
nregs = (rreg_ack & MASK_CMD_RW_REG_COUNT) + 1;
uint16_t start_addr = (rreg_ack & MASK_CMD_RW_REG_ADDRESS) >> 7;
for (int i = 0; i < nregs; i++) {
result[i] = get_unsigned_frame_word(frame, i + offset, true);
result[i] = get_unsigned_frame_word(rx_frame, i + offset, true);
}
print_command_response_to_string(rreg_addr_opcode, frame);
print_command_response_to_string(rreg_addr_opcode, rx_frame);
delay_microseconds_safe(1);
return result;
}

View File

@ -25,23 +25,28 @@ namespace ads131m08 {
static const uint8_t DEFAULT_WORD_LENGTH = 32; // we use 32 bit to allow for DMA transfers
static const int ADC_CHANNELS = 8;
static const int MAX_CHANNELS = 14; // for debugging
static const int MAX_CHANNELS = 15; // for debugging
static const int SAMPLE_TIME_SENSOR = 8; // for debugging
static const int MAX_SAMPLES_SENSOR = 9; // for debugging
static const int CRC_ERRORS_SENSOR = 10; // for debugging
static const int ISR_COUNT_SENSOR = 11; // for debugging
static const int ITERATIONS_SENSOR = 12; // for debugging
static const int NOT_READY_SENSOR = 13; // for debugging
static const int SPS_SENSOR = 14; // for debugging
// #define SET_IRAM IRAM_ATTR
#define SET_IRAM
typedef std::vector<uint8_t> spiframe;
typedef uint_str<uint16_t>::Ty_string uint16_str; // we want to use the stack to pass small arrays
typedef uint_str<float>::Ty_string float_str; // we want to use the stack to pass small arrays
class ADS131M08Hub : public Component,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_TRAILING,
spi::DATA_RATE_8MHZ> {
using Base = spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_8MHZ>;
friend class ads131m08_select;
public:
@ -91,7 +96,7 @@ class ADS131M08Hub : public Component,
bool set_channel_gain(uint8_t channel, uint8_t gain);
bool set_measure_rms(uint8_t channel, bool enable);
float get_sampled_value(uint8_t channel) { return sampled_values_[channel]; }
float get_average(uint8_t channel, bool read_ac);
//float get_average(uint8_t channel, bool read_ac);
bool set_reg_osr();
protected:
@ -110,7 +115,7 @@ class ADS131M08Hub : public Component,
uint8_t update_adc_word_length();
uint8_t update_adc_word_length(uint16_t status);
void SET_IRAM read_single();
uint16_str SET_IRAM read_multi();
float_str SET_IRAM read_multi();
bool adc_lock(bool enable);
bool adc_register_write(uint16_t address, uint16_t data);
bool adc_register_write(uint16_t address, const uint16_str &data);
@ -121,11 +126,7 @@ class ADS131M08Hub : public Component,
bool adc_soft_reset();
void adc_hard_reset();
void adc_sync();
void write_byte(uint8_t byte);
bool write(uint32_t data, uint8_t adcWordLength);
uint8_t read_byte();
void write_array(const spiframe &data);
void SET_IRAM read_array(spiframe &buffer);
void SET_IRAM transfer_array(spiframe &frame);
//void transfer_array(const spiframe &data_out, spiframe &data_in);
uint16_t SET_IRAM get_crc(const spiframe &frame);
bool SET_IRAM check_crc(const spiframe &frame_with_crc);
@ -137,7 +138,7 @@ class ADS131M08Hub : public Component,
bool SET_IRAM set_frame_word(spiframe &frame, int w_index, uint32_t data);
uint32_t SET_IRAM get_unsigned_frame_word(const spiframe &frame, int w_index, bool force_16bits = false);
int32_t SET_IRAM get_sign_ext_frame_word(const spiframe &frame, int w_index);
bool update_averages(uint8_t channel, float rms_ac, float rms_dc);
//bool update_averages(uint8_t channel, float rms_ac, float rms_dc);
std::atomic<int> adc_init_{0};
std::atomic<int> cs_ctr_{
0}; // Counter to track nested CS enable/disable calls for proper handling of multiple transfers in a row
@ -161,12 +162,24 @@ class ADS131M08Hub : public Component,
}
};
float update_conversion_factor();
//DRAM_ATTR static spiframe rx_frame;
inline void zero_fill(spiframe& frame) {
std::fill(frame.begin(), frame.end(), 0);
}
inline size_t setup_frame(spiframe& frame, uint8_t word_count) {
int word_nbytes = this->adc_word_length_ >> 3;
frame.resize(word_nbytes * word_count);
zero_fill(frame);
return frame.size();
}
private:
uint8_t update_state_[MAX_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t adc_word_length_{24};
float conversion_factor_{1.2 / 8388608.0}; // updated when word length changes
const uint32_t sample_time_ = 40000; // 250 ms
float conversion_factor_{1.25 / 8388608.0}; // updated when word length changes
const uint32_t sample_time_ = 20000; // 250 ms
float sps_{0.0f};
uint32_t num_samples_[ADC_CHANNELS];
float sample_sum_[ADC_CHANNELS];

View File

@ -9,7 +9,7 @@ AUTO_LOAD = [
"sensor", "voltage_sampler",
]
MAX_CHANNELS = 14
MAX_CHANNELS = 15
CONF_OFFSET_CALIBRATION = "offset_calibration"
CONF_GAIN_CALIBRATION = "gain_calibration"
CONF_PHASE_CALIBRATION = "phase_calibration"

View File

@ -73,10 +73,10 @@ void RMS_Sensor::loop()
}
}
}
else {
float value = this->parent_->get_average(this->calc_rms_);
publish_state(value);
}
//else {
// float value = this->parent_->get_average(this->calc_rms_);
// publish_state(value);
//}
}
void RMS_Sensor::dump_config()

View File

@ -26,7 +26,7 @@ class Channel : public sensor::Sensor,
void set_offset_calibration(int value) { this->offset_cal_ = value; }
void set_phase_calibration(int value) { this->phase_cal_ = value; }
bool set_calc_rms(bool enable) { this->calc_rms_ = enable; return this->parent_ != nullptr ? this->parent_->set_measure_rms(this->channel_, enable) : false; }
float get_average(bool read_ac) { return this->parent_->get_average(this->channel_, read_ac); }
//float get_average(bool read_ac) { return this->parent_->get_average(this->channel_, read_ac); }
void set_mux_input(ADC_INPUT_CHANNEL_MUX value) { this->input_ = value; }
uint32_t normalised_gain_calibration() const;
uint32_t normalised_offset_calibration() const;

View File

@ -14,7 +14,6 @@ from .. import CONF_ADS131M08_ID, ads131m08_ns
CONF_AC = "ac"
CONF_DC = "dc"
ICON_CURRENT_DC = "mdi:current-dc"
MAX_CHANNELS = 12
AUTO_LOAD = ["sensor",]
DEPENDENCIES = ["ads131m08"]