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:
parent
477f05a524
commit
d69d0b5dfb
@ -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));
|
||||
//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_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);
|
||||
|
||||
// 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) {
|
||||
// uint16_t ctr = isr_ctr_;
|
||||
// this->sensors_ac[ISR_COUNT_SENSOR]->publish_state(static_cast<float>(ctr));
|
||||
// }
|
||||
} 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)
|
||||
@ -692,6 +673,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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user