From 1b8ba88b0594809e1e0c2df975c86e9e7a86d265 Mon Sep 17 00:00:00 2001 From: Emanuele Trabattoni Date: Fri, 17 Apr 2026 11:01:41 +0200 Subject: [PATCH] ADC working ok in sync with system --- RotaxMonitor/lib/ADS1256/ADS1256.cpp | 66 +++++++++++++--------------- RotaxMonitor/lib/ADS1256/ADS1256.h | 3 ++ RotaxMonitor/src/datasave.cpp | 46 ++++++++++--------- RotaxMonitor/src/main.cpp | 32 ++++++++------ RotaxMonitor/src/tasks.cpp | 17 +++---- 5 files changed, 84 insertions(+), 80 deletions(-) diff --git a/RotaxMonitor/lib/ADS1256/ADS1256.cpp b/RotaxMonitor/lib/ADS1256/ADS1256.cpp index 3372b47..eef8eac 100644 --- a/RotaxMonitor/lib/ADS1256/ADS1256.cpp +++ b/RotaxMonitor/lib/ADS1256/ADS1256.cpp @@ -74,21 +74,21 @@ void ADS1256::InitializeADC() writeRegister(STATUS_REG, _STATUS); delay(200); - _MUX = 0b00000001; //MUX AIN0+AIN1 + _MUX = DIFF_0_1; //MUX AIN0+AIN1 writeRegister(MUX_REG, _MUX); delay(200); - _ADCON = 0b00000000; //ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) + _ADCON = WAKEUP; //ADCON - CLK: OFF, SDCS: OFF, PGA = 0 (+/- 5 V) writeRegister(ADCON_REG, _ADCON); delay(200); updateConversionParameter(); - _DRATE = 0b10000010; //100SPS + _DRATE = DRATE_100SPS; //100SPS writeRegister(DRATE_REG, _DRATE); delay(200); - sendDirectCommand(0b11110000); //Offset and self-gain calibration + sendDirectCommand(SELFCAL); //Offset and self-gain calibration delay(200); _isAcquisitionRunning = false; //MCU will be waiting to start a continuous acquisition @@ -109,7 +109,7 @@ void ADS1256::waitForHighDRDY() void ADS1256::stopConversion() //Sending SDATAC to stop the continuous conversion { waitForLowDRDY(); //SDATAC should be called after DRDY goes LOW (p35. Figure 33) - _spi->transfer(0b00001111); //Send SDATAC to the ADC + _spi->transfer(SDATAC); //Send SDATAC to the ADC CS_HIGH(); //We finished the command sequence, so we switch it back to HIGH _spi->endTransaction(); @@ -465,7 +465,7 @@ uint8_t ADS1256::readGPIO(uint8_t gpioPin) //Reading GPIO void ADS1256::sendDirectCommand(uint8_t directCommand) { //Direct commands can be found in the datasheet Page 34, Table 24. - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" delayMicroseconds(5); @@ -486,14 +486,14 @@ void ADS1256::writeRegister(uint8_t registerAddress, uint8_t registerValueToWrit { waitForLowDRDY(); - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); //SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] delayMicroseconds(5); //see t6 in the datasheet - _spi->transfer(0x50 | registerAddress); // 0x50 = 01010000 = WREG + _spi->transfer(WREG | registerAddress); // 0x50 = 01010000 = WREG _spi->transfer(0x00); //2nd (empty) command byte @@ -509,18 +509,18 @@ long ADS1256::readRegister(uint8_t registerAddress) //Reading a register { waitForLowDRDY(); - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); //SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1. CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(0x10 | registerAddress); //0x10 = 0001000 = RREG - OR together the two numbers (command + address) + _spi->transfer(RREG | registerAddress); //0x10 = 0001000 = RREG - OR together the two numbers (command + address) _spi->transfer(0x00); //2nd (empty) command byte delayMicroseconds(5); //see t6 in the datasheet - uint8_t regValue = _spi->transfer(0xFF); //read out the register value + uint8_t regValue = _spi->transfer(0x00); //read out the register value CS_HIGH(); _spi->endTransaction(); @@ -531,10 +531,10 @@ long ADS1256::readRegister(uint8_t registerAddress) //Reading a register long ADS1256::readSingle() //Reading a single value ONCE using the RDATA command { - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" waitForLowDRDY(); - _spi->transfer(0b00000001); //Issue RDATA (0000 0001) command + _spi->transfer(RDATA); //Issue RDATA (0000 0001) command delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. _outputBuffer[0] = _spi->transfer(0); // MSB @@ -556,10 +556,10 @@ long ADS1256::readSingleContinuous() //Reads the recently selected input channel if(_isAcquisitionRunning == false) { _isAcquisitionRunning = true; - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); CS_LOW(); //REF: P34: "CS must stay low during the entire command sequence" waitForLowDRDY(); - _spi->transfer(0b00000011); //Issue RDATAC (0000 0011) + _spi->transfer(RDATAC); //Issue RDATAC (0000 0011) delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. } else @@ -585,14 +585,12 @@ long ADS1256::cycleSingle() { _isAcquisitionRunning = true; _cycle = 0; - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(0x50 | 1); // 0x50 = WREG //1 = MUX + _spi->transfer(WREG | MUX_REG); // 0x50 = WREG //1 = MUX _spi->transfer(0x00); _spi->transfer(SING_0); //AIN0+AINCOM - CS_HIGH(); - delay(50); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] + delayMicroseconds(250); } else {} @@ -638,18 +636,18 @@ long ADS1256::cycleSingle() break; } //Step 2. - _spi->transfer(0b11111100); //SYNC + _spi->transfer(SYNC); //SYNC delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us - _spi->transfer(0b11111111); //WAKEUP + _spi->transfer(WAKEUP); //WAKEUP //Step 3. //Issue RDATA (0000 0001) command - _spi->transfer(0b00000001); + _spi->transfer(RDATA); delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. - _outputBuffer[0] = _spi->transfer(0x0F); // MSB - _outputBuffer[1] = _spi->transfer(0x0F); // Mid-byte - _outputBuffer[2] = _spi->transfer(0x0F); // LSB + _outputBuffer[0] = _spi->transfer(0); // MSB + _outputBuffer[1] = _spi->transfer(0); // Mid-byte + _outputBuffer[2] = _spi->transfer(0); // LSB _outputValue = ((long)_outputBuffer[0]<<16) | ((long)_outputBuffer[1]<<8) | (_outputBuffer[2]); _outputValue = convertSigned24BitToLong(_outputValue); @@ -670,16 +668,14 @@ long ADS1256::cycleDifferential() { _cycle = 0; _isAcquisitionRunning = true; - _spi->beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); + _spi->beginTransaction(SPISettings(SPI_FREQ, MSBFIRST, SPI_MODE1)); //Set the AIN0+AIN1 as inputs manually CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] - _spi->transfer(0x50 | 1); // 0x50 = WREG //1 = MUX + _spi->transfer(WREG | MUX_REG); // 0x50 = WREG //1 = MUX _spi->transfer(0x00); _spi->transfer(DIFF_0_1); //AIN0+AIN1 - CS_HIGH(); - delay(50); - CS_LOW(); //CS must stay LOW during the entire sequence [Ref: P34, T24] + delayMicroseconds(250); } else {} @@ -710,12 +706,12 @@ long ADS1256::cycleDifferential() break; } - _spi->transfer(0b11111100); //SYNC + _spi->transfer(SYNC); //SYNC delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us - _spi->transfer(0b11111111); //WAKEUP + _spi->transfer(WAKEUP); //WAKEUP //Step 3. - _spi->transfer(0b00000001); //Issue RDATA (0000 0001) command + _spi->transfer(RDATA); //Issue RDATA (0000 0001) command delayMicroseconds(7); //Wait t6 time (~6.51 us) REF: P34, FIG:30. _outputBuffer[0] = _spi->transfer(0); // MSB @@ -744,7 +740,7 @@ void ADS1256::updateConversionParameter() void ADS1256::updateMUX(uint8_t muxValue) { - _spi->transfer(0x50 | MUX_REG); //Write to the MUX register (0x50 is the WREG command) + _spi->transfer(WREG | MUX_REG); //Write to the MUX register (0x50 is the WREG command) _spi->transfer(0x00); _spi->transfer(muxValue); //Write the new MUX value } diff --git a/RotaxMonitor/lib/ADS1256/ADS1256.h b/RotaxMonitor/lib/ADS1256/ADS1256.h index 1ded2e2..35ade99 100644 --- a/RotaxMonitor/lib/ADS1256/ADS1256.h +++ b/RotaxMonitor/lib/ADS1256/ADS1256.h @@ -15,6 +15,9 @@ #include +// SPI Frequency +#define SPI_FREQ 1920000 + //Differential inputs #define DIFF_0_1 0b00000001 //A0 + A1 as differential input #define DIFF_2_3 0b00100011 //A2 + A3 as differential input diff --git a/RotaxMonitor/src/datasave.cpp b/RotaxMonitor/src/datasave.cpp index c1ae86c..5fb8305 100644 --- a/RotaxMonitor/src/datasave.cpp +++ b/RotaxMonitor/src/datasave.cpp @@ -47,31 +47,29 @@ void ignitionBoxStatusFiltered::update(const ignitionBoxStatus &new_status) } m_count++; // simple moving average calculation - m_last.timestamp = new_status.timestamp; // keep timestamp of latest status + m_last.timestamp = new_status.timestamp; // keep timestamp of latest status + m_last.coils12.n_events = new_status.coils12.n_events; // sum events instead of averaging + m_last.coils12.n_missed_firing = new_status.coils12.n_missed_firing; // sum missed firings instead of averaging + m_last.coils12.spark_status = new_status.coils12.spark_status; // take latest spark status + m_last.coils12.sstart_status = new_status.coils12.sstart_status; // take latest soft start status + filter(m_last.coils12.spark_delay, new_status.coils12.spark_delay, m_max_count); // incremental average calculation + filter(m_last.coils12.peak_p_in, new_status.coils12.peak_p_in, m_max_count); // incremental average calculation + filter(m_last.coils12.peak_n_in, new_status.coils12.peak_n_in, m_max_count); // incremental average calculation + filter(m_last.coils12.peak_p_out, new_status.coils12.peak_p_out, m_max_count); // incremental average calculation + filter(m_last.coils12.peak_n_out, new_status.coils12.peak_n_out, m_max_count); // incremental average calculation - m_last.coils12.n_events = new_status.coils12.n_events; // sum events instead of averaging - m_last.coils12.n_missed_firing = new_status.coils12.n_missed_firing; // sum missed firings instead of averaging - m_last.coils12.spark_status = new_status.coils12.spark_status; // take latest spark status - m_last.coils12.sstart_status = new_status.coils12.sstart_status; // take latest soft start status - m_last.coils12.spark_delay = new_status.coils12.spark_delay; // incremental average calculation - m_last.coils12.peak_p_in = new_status.coils12.peak_p_in; // incremental average calculation - m_last.coils12.peak_n_in = new_status.coils12.peak_n_in; // incremental average calculation - m_last.coils12.peak_p_out = new_status.coils12.peak_p_out; // incremental average calculation - m_last.coils12.peak_n_out = new_status.coils12.peak_n_out; // incremental average calculation - - m_last.coils34.n_events = new_status.coils34.n_events; // sum events instead of averaging - m_last.coils34.n_missed_firing = new_status.coils34.n_missed_firing; // sum missed firings instead of averaging - m_last.coils34.spark_status = new_status.coils34.spark_status; // take latest spark status - m_last.coils34.sstart_status = new_status.coils34.sstart_status; // take latest soft start status - m_last.coils34.spark_delay = new_status.coils34.spark_delay; // incremental average calculation - m_last.coils34.peak_p_in = new_status.coils34.peak_p_in; // incremental average calculation - m_last.coils34.peak_n_in = new_status.coils34.peak_n_in; // incremental average calculation - m_last.coils34.peak_p_out = new_status.coils34.peak_p_out; // incremental average calculation - m_last.coils34.peak_n_out = new_status.coils34.peak_n_out; // incremental average calculation - - m_last.eng_rpm = new_status.eng_rpm; // incremental average calculation - m_last.adc_read_time = m_last.adc_read_time; // incremental average calculation - m_last.n_queue_errors = new_status.n_queue_errors; // take last of queue errors since it's a cumulative count of errors in the queue, not an average value + m_last.coils34.n_events = new_status.coils34.n_events; // sum events instead of averaging + m_last.coils34.n_missed_firing = new_status.coils34.n_missed_firing; // sum missed firings instead of averaging + m_last.coils34.spark_status = new_status.coils34.spark_status; // take latest spark status + m_last.coils34.sstart_status = new_status.coils34.sstart_status; // take latest soft start status + filter(m_last.coils34.spark_delay, new_status.coils34.spark_delay, m_max_count); // incremental average calculation + filter(m_last.coils34.peak_p_in, new_status.coils34.peak_p_in, m_max_count); // incremental average calculation + filter(m_last.coils34.peak_n_in, new_status.coils34.peak_n_in, m_max_count); // incremental average calculation + filter(m_last.coils34.peak_p_out, new_status.coils34.peak_p_out, m_max_count); // incremental average calculation + filter(m_last.coils34.peak_n_out, new_status.coils34.peak_n_out, m_max_count); // incremental average calculation + filter(m_last.eng_rpm, new_status.eng_rpm, m_max_count); // incremental average calculation // incremental average calculation + filter(m_last.adc_read_time, m_last.adc_read_time, m_max_count); // incremental average calculation + m_last.n_queue_errors = new_status.n_queue_errors; if (m_count >= m_max_count) { diff --git a/RotaxMonitor/src/main.cpp b/RotaxMonitor/src/main.cpp index 858a01d..7ae1830 100644 --- a/RotaxMonitor/src/main.cpp +++ b/RotaxMonitor/src/main.cpp @@ -123,35 +123,41 @@ void loop() // Configure ADCs dev->m_adc_a->InitializeADC(); dev->m_adc_a->setPGA(PGA_1); - // dev->m_adc_a->setDRATE(DRATE_15000SPS); + dev->m_adc_a->setDRATE(DRATE_7500SPS); #ifdef CH_B_ENABLE dev->m_adc_b->InitializeADC(); dev->m_adc_b->setPGA(PGA_1); dev->m_adc_b->setDRATE(DRATE_30000SPS); #endif LOG_DEBUG("Init SPI OK"); - + uint8_t chs[8] = { - SING_0, SING_1, SING_2, SING_3, SING_4, SING_5, SING_6, SING_7 - }; + SING_0, SING_1, SING_2, SING_3, SING_4, SING_5, SING_6, SING_7}; float res[8]; + auto timeout = Serial.getTimeout(); + Serial.setTimeout(0); + uint64_t count = 0; while (Serial.read() != 's') // The conversion is stopped by a character received from the serial port { - clearScreen(); auto start = esp_timer_get_time(); - for (int i = 0; i < 8; i++){ - // dev->m_adc_a->setMUX(chs[i]); - res[i] = dev->m_adc_a->convertToVoltage(dev->m_adc_a->cycleSingle()); + for (int i = 0; i < 8; i++) + { + // dev->m_adc_a->setMUX(chs[i]); + res[i] += 0.1f * (dev->m_adc_a->convertToVoltage(dev->m_adc_a->cycleSingle()) - res[i]); } auto stop = esp_timer_get_time(); - for (int j = 0; j < 8; j++){ - Serial.printf("ADC_A SING_%d: %5.4f\n",j, res[j]); + if (count++ % 25 == 0) + { + clearScreen(); + for (int j = 0; j < 8; j++) + { + Serial.printf("ADC_A SING_%d: %5.4f\n", j, res[j]); + } + Serial.printf("ADC Time: %5.3f ms\n", (float)((stop - start) / 1000.0f)); } - Serial.printf("ADC Time: %u us\n", stop-start); - delay(100); - } + Serial.setTimeout(timeout); dev->m_adc_a->stopConversion(); //////// INIT I2C INTERFACES //////// diff --git a/RotaxMonitor/src/tasks.cpp b/RotaxMonitor/src/tasks.cpp index 40a789e..e23df0c 100644 --- a/RotaxMonitor/src/tasks.cpp +++ b/RotaxMonitor/src/tasks.cpp @@ -238,15 +238,16 @@ void rtIgnitionTask::rtIgnitionTask_realtime(void *pvParameters) std::lock_guard lock(spi_mutex); uint32_t start_adc_read = esp_timer_get_time(); // from peak detector circuits - ign_box_sts.coils12.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_12P_IN); - ign_box_sts.coils12.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_12N_IN); - ign_box_sts.coils34.peak_p_in = adcReadChannel(adc, ADC_CH_PEAK_34P_IN); - ign_box_sts.coils34.peak_n_in = adcReadChannel(adc, ADC_CH_PEAK_34N_IN); - ign_box_sts.coils12.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_12P_OUT); - ign_box_sts.coils12.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_12N_OUT); - ign_box_sts.coils34.peak_p_out = adcReadChannel(adc, ADC_CH_PEAK_34P_OUT); - ign_box_sts.coils34.peak_n_out = adcReadChannel(adc, ADC_CH_PEAK_34N_OUT); + ign_box_sts.coils12.peak_p_in = adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils12.peak_n_in = adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils34.peak_p_in = adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils34.peak_n_in = adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils12.peak_p_out =adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils12.peak_n_out =adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils34.peak_p_out =adc->convertToVoltage(adc->cycleSingle()); + ign_box_sts.coils34.peak_n_out =adc->convertToVoltage(adc->cycleSingle()); ign_box_sts.adc_read_time = (int32_t)(esp_timer_get_time() - start_adc_read); + adc->stopConversion(); } else // simulate adc read timig vTaskDelay(pdMS_TO_TICKS(c_adc_time));