Index: AD5941_interface09302025/ad5941_library_extension.cpp =================================================================== diff -u -r4be37523c8348f40b96b1df7a4ef376e99c204f6 -r3c0eedb1a41ef5151d9772f5770918e8e7f1fd25 --- AD5941_interface09302025/ad5941_library_extension.cpp (.../ad5941_library_extension.cpp) (revision 4be37523c8348f40b96b1df7a4ef376e99c204f6) +++ AD5941_interface09302025/ad5941_library_extension.cpp (.../ad5941_library_extension.cpp) (revision 3c0eedb1a41ef5151d9772f5770918e8e7f1fd25) @@ -133,8 +133,8 @@ static eepromDataPacketStruct eepromDataPacket; // Stores all the eeprom data static measurementSettingsStruct measurementSettingsPacket; // Stores all the conductivity measurement settings static measurementSettingsStruct tempSettings; // Stores received measurement settings to be updated. -static Update_cfg_Status updateCfgStatus[MAX_CONDUCTIVITY_MST_PARAM_IDX]; -static Update_EEPROM_Status updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_CMD; +static Update_cfg_Status updateCfgStatus[MAX_CONDUCTIVITY_MST_PARAM_IDX]; // Stores all configuration statuses for each measurement setting +static Update_EEPROM_Status updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_CMD; // Stores eeprom status // Global variable to store the last known good configuration SavedConfig lastConfig; @@ -2815,213 +2815,93 @@ } } - void beginSerial(Stream * s, unsigned long baud) +void beginSerial(Stream * s, unsigned long baud) +{ + if (s == &Serial) { - if (s == &Serial) + Serial.begin(baud); + } + else if (s == &Serial1) + { + Serial1.begin(baud); + } + else if (s == &Serial2) + { + Serial2.begin(baud); + } + else if (s == &Serial3) + { + Serial3.begin(baud); + } + else if (s == &Serial4) + { + Serial4.begin(baud); + } + else if (s == &Serial5) + { + Serial5.begin(baud); + } + else if (s == &Serial6) + { + Serial6.begin(baud); + } + else if (s == &Serial7) + { + Serial7.begin(baud); + } +} + +// Function to measure all successfully initialized units +bool getAllMesaurements(void) +{ + int successCount = 0; + bool retVal = true; // Success + + // Count successful units first + for (int i = 0; i < 6; i++) + { + if (unitStatus[i] == STATUS_SUCCESS) { - Serial.begin(baud); + successCount++; } - else if (s == &Serial1) - { - Serial1.begin(baud); - } - else if (s == &Serial2) - { - Serial2.begin(baud); - } - else if (s == &Serial3) - { - Serial3.begin(baud); - } - else if (s == &Serial4) - { - Serial4.begin(baud); - } - else if (s == &Serial5) - { - Serial5.begin(baud); - } - else if (s == &Serial6) - { - Serial6.begin(baud); - } - else if (s == &Serial7) - { - Serial7.begin(baud); - } } - // Function to measure all successfully initialized units - bool getAllMesaurements(void) + // If no successful units, report and return + if (successCount == 0) { - int successCount = 0; - bool retVal = true; // Success + retVal = false; // Error + // activeSerial->println("No successfully initialized units to measure!"); + return retVal; + } - // Count successful units first - for (int i = 0; i < 6; i++) - { - if (unitStatus[i] == STATUS_SUCCESS) - { - successCount++; - } - } + AppIMPCfg_Type *pImpedanceCfg; - // If no successful units, report and return - if (successCount == 0) + // Loop through and measure each successful unit + for (int unit = 1; unit <= 6; unit++) + { + // Skip units that aren't successfully initialized + if (unitStatus[unit - 1] != STATUS_SUCCESS) { - retVal = false; // Error - // activeSerial->println("No successfully initialized units to measure!"); - return retVal; + continue; } - AppIMPCfg_Type *pImpedanceCfg; - - // Loop through and measure each successful unit - for (int unit = 1; unit <= 6; unit++) + // Select the unit + selectUnit(unit); + if (propagateSettingsChanges) { - // Skip units that aren't successfully initialized - if (unitStatus[unit - 1] != STATUS_SUCCESS) - { - continue; - } - - // Select the unit - selectUnit(unit); - if (propagateSettingsChanges) - { - AppIMPGetCfg(&pImpedanceCfg); - pImpedanceCfg->bParaChanged = bTRUE; - } - // Allow some settling time after switching units - delay(50); - - // quick patch for fixing spontaneous measurements - unsigned long currentMillis = millis(); - if (currentMillis - previousMillis >= jitterTimeout) - { - // Run multiple settling measurements in a loop - for (int settling = 0; settling < numSettlingMeasurements; settling++) - { - // Run one complete measurement cycle but discard results - AppIMPInit(AppBuff, APPBUFF_SIZE); - AppIMPCtrl(IMPCTRL_START, 0); - - // Wait for completion (simplified polling) - int timeout_count = 0; - while (AD5940_GetMCUIntFlag() != 1 && timeout_count < 1000) - { - delay(1); - timeout_count++; - } - - if (AD5940_GetMCUIntFlag() == 1) - { - AD5940_ClrMCUIntFlag(); - uint32_t dummy_size = APPBUFF_SIZE; - AppIMPISR(AppBuff, &dummy_size); // Discard this data - } - - AppIMPCtrl(IMPCTRL_STOPSYNC, 0); - - // Small delay between settling measurements - if (settling < numSettlingMeasurements - 1) - { - AD5940_Delay10us(1000); // 10ms between measurements - } - } - } - - // Perform impedance measurement - for (int i = 0; i < repeatNumber; i++) - { - AppIMPMeasure(i); - } - float medianMag; - float medianPhase; - - // take median and output results - if (repeatNumber == 1) - { - medianMag = magnitudeArray[0]; - medianPhase = phaseArray[0]; - } - else - { - medianMag = calculateMedian(magnitudeArray, repeatNumber); - medianPhase = calculateMedian(phaseArray, repeatNumber); - } - - // Perform RTD (temperature) measurement - float rtd_res = getRTDMeasurements(rtdVoltageValue); - - previousMillis = millis(); - - // Check for "ERROR: AD5940 wakeup timeout" - if (-1000.0f == rtd_res) - { - // In case of an error, send all 0's - initPacketToDefault(unit); - } - if (false == isSensorInitialized(unit)) - { - // In case the unit is not initialized, send all 0's - initPacketToDefault(unit); - } - // Pack data for case 'g' - else - { - // Pack the sensor data - // The ALY code loops from 1 to 6. Our packet index from 0 to 5. So, index at i-1. - int sensorIdx = unit - 1; - sensorPacket[sensorIdx].sensorNum = unit; // Conductivity Sensor number i.e unit 1 to 6. - sensorPacket[sensorIdx].impFreq = storedFrequency; // Impedance Frequency - sensorPacket[sensorIdx].impDataPoints = 1; // Impedance Data Points. Hard coded to 1 - sensorPacket[sensorIdx].impRzMag = medianMag; // Value of medianMag - sensorPacket[sensorIdx].impRzPhase = medianPhase; // Value of medianPhase - sensorPacket[sensorIdx].rtdFreq = 0; // RTD Frequency. Hard coded to 0.0 - sensorPacket[sensorIdx].rtdDataPoints = 1; // Impedance Data Points. Hard coded to 1 - sensorPacket[sensorIdx].rtdRzMag = rtd_res; // Value of rtd_resistance - sensorPacket[sensorIdx].rtdRzPhase = 0.0; // RTD Rz Phase. Hard coded to 0.0 - - // Reusing this function for case 'm' - if (sendSensorData) - { - singleSensorPacket.sensorNum = sensorPacket[sensorIdx].sensorNum; - singleSensorPacket.impFreq = sensorPacket[sensorIdx].impFreq; // Impedance Frequency - singleSensorPacket.impDataPoints = sensorPacket[sensorIdx].impDataPoints; // Impedance Data Points. Hard coded to 1 - singleSensorPacket.impRzMag = sensorPacket[sensorIdx].impRzMag; // Value of medianMag - singleSensorPacket.impRzPhase = sensorPacket[sensorIdx].impRzPhase; // Value of medianPhase - singleSensorPacket.rtdFreq = sensorPacket[sensorIdx].rtdFreq; // RTD Frequency. Hard coded to 0.0 - singleSensorPacket.rtdDataPoints = sensorPacket[sensorIdx].rtdDataPoints; // Impedance Data Points. Hard coded to 1 - singleSensorPacket.rtdRzMag = sensorPacket[sensorIdx].rtdRzMag; // Value of rtd_resistance - singleSensorPacket.rtdRzPhase = sensorPacket[sensorIdx].rtdRzPhase; // RTD Rz Phase. Hard coded to 0.0 - } - } + AppIMPGetCfg(&pImpedanceCfg); + pImpedanceCfg->bParaChanged = bTRUE; } + // Allow some settling time after switching units + delay(50); - propagateSettingsChanges = 0; - return retVal; - } - - void getSelectedSensorMeasurements(void) - { // quick patch for fixing spontaneous measurements unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= jitterTimeout) { - // Run multiple settling measurements in a loop for (int settling = 0; settling < numSettlingMeasurements; settling++) { - if (settling == 0) - { - // activeSerial->println("Performing settling measurements..."); - } - if (verboseMode) - { - // activeSerial->printf(" Settling Measurement#: %u ", settling); - // activeSerial->println(" "); - } // Run one complete measurement cycle but discard results AppIMPInit(AppBuff, APPBUFF_SIZE); AppIMPCtrl(IMPCTRL_START, 0); @@ -3049,65 +2929,16 @@ AD5940_Delay10us(1000); // 10ms between measurements } } - if (verboseMode) - { - // activeSerial->println(" End Settling Measurements"); - } } - if (verboseMode) - { - // activeSerial->println("Conductivity"); - // activeSerial->print(" Conductivity TIA Resistor: "); - switch (DEFAULT_RTIA) - { - case HSTIARTIA_200: - // activeSerial->println("200 Ohm"); - break; - case HSTIARTIA_1K: - // activeSerial->println("1K Ohm"); - break; - case HSTIARTIA_5K: - // activeSerial->println("5K Ohm"); - break; - case HSTIARTIA_10K: - // activeSerial->println("10K Ohm"); - break; - case HSTIARTIA_20K: - // activeSerial->println("20K Ohm"); - break; - case HSTIARTIA_40K: - // activeSerial->println("40K Ohm"); - break; - case HSTIARTIA_80K: - // activeSerial->println("80K Ohm"); - break; - case HSTIARTIA_160K: - // activeSerial->println("160K Ohm"); - break; - default: - // activeSerial->println("Unknown"); - break; - } - } // Perform impedance measurement for (int i = 0; i < repeatNumber; i++) { AppIMPMeasure(i); } - if (verboseMode) - { - if (AD5940_IsAdcMaxSaturatedAndClear()) - { - // activeSerial->println("SaturationFlag tripped!"); - } - else - { - // activeSerial->println("SaturationFlag NOT tripped!"); - } - } float medianMag; float medianPhase; + // take median and output results if (repeatNumber == 1) { @@ -3120,751 +2951,920 @@ medianPhase = calculateMedian(phaseArray, repeatNumber); } - // activeSerial->printf("Freq: %.2f Hz ", storedFrequency); - - // Print the number of data points - // activeSerial->printf("DataPoints: %lu ", 1); - - // Print magnitude in ohms and phase in degrees - // Note: Converting phase from radians to degrees (phase * 180 / π) - // activeSerial->printf("RzMag: %.2f Ohm, RzPhase: %.2f deg", - // medianMag, - // medianPhase); - - // Add separator and perform RTD (temperature) measurement - // activeSerial->print(";"); + // Perform RTD (temperature) measurement float rtd_res = getRTDMeasurements(rtdVoltageValue); - // activeSerial->print("*"); + previousMillis = millis(); // Check for "ERROR: AD5940 wakeup timeout" if (-1000.0f == rtd_res) { // In case of an error, send all 0's - initSinglePacketToDefault(); + initPacketToDefault(unit); } + if (false == isSensorInitialized(unit)) + { + // In case the unit is not initialized, send all 0's + initPacketToDefault(unit); + } + // Pack data for case 'g' else { - singleSensorPacket.impFreq = storedFrequency; // Impedance Frequency - singleSensorPacket.impDataPoints = 1; // Impedance Data Points. Hard coded to 1 - singleSensorPacket.impRzMag = medianMag; // Value of medianMag - singleSensorPacket.impRzPhase = medianPhase; // Value of medianPhase - singleSensorPacket.rtdFreq = 0; // RTD Frequency. Hard coded to 0.0 - singleSensorPacket.rtdDataPoints = 1; // Impedance Data Points. Hard coded to 1 - singleSensorPacket.rtdRzMag = rtd_res; // Value of rtd_resistance - singleSensorPacket.rtdRzPhase = 0.0; // RTD Rz Phase. Hard coded to 0.0 + // Pack the sensor data + // The ALY code loops from 1 to 6. Our packet index from 0 to 5. So, index at i-1. + int sensorIdx = unit - 1; + sensorPacket[sensorIdx].sensorNum = unit; // Conductivity Sensor number i.e unit 1 to 6. + sensorPacket[sensorIdx].impFreq = storedFrequency; // Impedance Frequency + sensorPacket[sensorIdx].impDataPoints = 1; // Impedance Data Points. Hard coded to 1 + sensorPacket[sensorIdx].impRzMag = medianMag; // Value of medianMag + sensorPacket[sensorIdx].impRzPhase = medianPhase; // Value of medianPhase + sensorPacket[sensorIdx].rtdFreq = 0; // RTD Frequency. Hard coded to 0.0 + sensorPacket[sensorIdx].rtdDataPoints = 1; // Impedance Data Points. Hard coded to 1 + sensorPacket[sensorIdx].rtdRzMag = rtd_res; // Value of rtd_resistance + sensorPacket[sensorIdx].rtdRzPhase = 0.0; // RTD Rz Phase. Hard coded to 0.0 + + // Reusing this function for case 'm' + if (sendSensorData) + { + singleSensorPacket.sensorNum = sensorPacket[sensorIdx].sensorNum; + singleSensorPacket.impFreq = sensorPacket[sensorIdx].impFreq; // Impedance Frequency + singleSensorPacket.impDataPoints = sensorPacket[sensorIdx].impDataPoints; // Impedance Data Points. Hard coded to 1 + singleSensorPacket.impRzMag = sensorPacket[sensorIdx].impRzMag; // Value of medianMag + singleSensorPacket.impRzPhase = sensorPacket[sensorIdx].impRzPhase; // Value of medianPhase + singleSensorPacket.rtdFreq = sensorPacket[sensorIdx].rtdFreq; // RTD Frequency. Hard coded to 0.0 + singleSensorPacket.rtdDataPoints = sensorPacket[sensorIdx].rtdDataPoints; // Impedance Data Points. Hard coded to 1 + singleSensorPacket.rtdRzMag = sensorPacket[sensorIdx].rtdRzMag; // Value of rtd_resistance + singleSensorPacket.rtdRzPhase = sensorPacket[sensorIdx].rtdRzPhase; // RTD Rz Phase. Hard coded to 0.0 + } } - activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); } - float getRTDMeasurements(float sensor_mV) + propagateSettingsChanges = 0; + return retVal; +} + +void getSelectedSensorMeasurements(void) +{ + // quick patch for fixing spontaneous measurements + unsigned long currentMillis = millis(); + if (currentMillis - previousMillis >= jitterTimeout) { - AFERefCfg_Type aferef_cfg; - HSLoopCfg_Type HsLoopCfg; - DSPCfg_Type dsp_cfg; - uint32_t adcCode_rtd, adcCode_ref; - float volt_rtd, volt_ref; - float rtd_resistance; - const float RtdRefRes = REF_RESISTOR_VALUE; + // Run multiple settling measurements in a loop + for (int settling = 0; settling < numSettlingMeasurements; settling++) + { + if (settling == 0) + { + // activeSerial->println("Performing settling measurements..."); + } + if (verboseMode) + { + // activeSerial->printf(" Settling Measurement#: %u ", settling); + // activeSerial->println(" "); + } + // Run one complete measurement cycle but discard results + AppIMPInit(AppBuff, APPBUFF_SIZE); + AppIMPCtrl(IMPCTRL_START, 0); - // Wake up the AD5940 from low power mode - if (AD5940_WakeUp(10) > 10) + // Wait for completion (simplified polling) + int timeout_count = 0; + while (AD5940_GetMCUIntFlag() != 1 && timeout_count < 1000) + { + delay(1); + timeout_count++; + } + + if (AD5940_GetMCUIntFlag() == 1) + { + AD5940_ClrMCUIntFlag(); + uint32_t dummy_size = APPBUFF_SIZE; + AppIMPISR(AppBuff, &dummy_size); // Discard this data + } + + AppIMPCtrl(IMPCTRL_STOPSYNC, 0); + + // Small delay between settling measurements + if (settling < numSettlingMeasurements - 1) + { + AD5940_Delay10us(1000); // 10ms between measurements + } + } + if (verboseMode) { - // activeSerial->println("ERROR: AD5940 wakeup timeout"); - return -1000.0f; + // activeSerial->println(" End Settling Measurements"); } + } - // Reset LPDAC configuration before RTD measurement - LPDACCfg_Type lpdac_reset = {0}; - lpdac_reset.PowerEn = bFALSE; - AD5940_LPDACCfgS(&lpdac_reset); + if (verboseMode) + { + // activeSerial->println("Conductivity"); + // activeSerial->print(" Conductivity TIA Resistor: "); + switch (DEFAULT_RTIA) + { + case HSTIARTIA_200: + // activeSerial->println("200 Ohm"); + break; + case HSTIARTIA_1K: + // activeSerial->println("1K Ohm"); + break; + case HSTIARTIA_5K: + // activeSerial->println("5K Ohm"); + break; + case HSTIARTIA_10K: + // activeSerial->println("10K Ohm"); + break; + case HSTIARTIA_20K: + // activeSerial->println("20K Ohm"); + break; + case HSTIARTIA_40K: + // activeSerial->println("40K Ohm"); + break; + case HSTIARTIA_80K: + // activeSerial->println("80K Ohm"); + break; + case HSTIARTIA_160K: + // activeSerial->println("160K Ohm"); + break; + default: + // activeSerial->println("Unknown"); + break; + } + } + // Perform impedance measurement + for (int i = 0; i < repeatNumber; i++) + { + AppIMPMeasure(i); + } + if (verboseMode) + { + if (AD5940_IsAdcMaxSaturatedAndClear()) + { + // activeSerial->println("SaturationFlag tripped!"); + } + else + { + // activeSerial->println("SaturationFlag NOT tripped!"); + } + } + float medianMag; + float medianPhase; + // take median and output results + if (repeatNumber == 1) + { + medianMag = magnitudeArray[0]; + medianPhase = phaseArray[0]; + } + else + { + medianMag = calculateMedian(magnitudeArray, repeatNumber); + medianPhase = calculateMedian(phaseArray, repeatNumber); + } - // Configure High-Speed Loop - HsLoopCfg.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2; - HsLoopCfg.HsDacCfg.HsDacGain = HSDACGAIN_1; - HsLoopCfg.HsDacCfg.HsDacUpdateRate = 7; + // activeSerial->printf("Freq: %.2f Hz ", storedFrequency); - // TIA settings - HsLoopCfg.HsTiaCfg.DiodeClose = bFALSE; - HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1; - HsLoopCfg.HsTiaCfg.HstiaCtia = 32; - HsLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN; - HsLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN; - HsLoopCfg.HsTiaCfg.HstiaRtiaSel = RTD_RTIA; + // Print the number of data points + // activeSerial->printf("DataPoints: %lu ", 1); - // Switch matrix for RTD measurement - HsLoopCfg.SWMatCfg.Dswitch = RTD_DSWITCH; - HsLoopCfg.SWMatCfg.Pswitch = RTD_PSWITCH; - HsLoopCfg.SWMatCfg.Nswitch = RTD_NSWITCH; - HsLoopCfg.SWMatCfg.Tswitch = RTD_TSWITCH; + // Print magnitude in ohms and phase in degrees + // Note: Converting phase from radians to degrees (phase * 180 / π) + // activeSerial->printf("RzMag: %.2f Ohm, RzPhase: %.2f deg", + // medianMag, + // medianPhase); - // Configure waveform generator - HsLoopCfg.WgCfg.WgType = WGTYPE_MMR; - HsLoopCfg.WgCfg.GainCalEn = bFALSE; - HsLoopCfg.WgCfg.OffsetCalEn = bFALSE; - uint32_t code = mV_to_WgCode(sensor_mV); - HsLoopCfg.WgCfg.WgCode = code; + // Add separator and perform RTD (temperature) measurement + // activeSerial->print(";"); + float rtd_res = getRTDMeasurements(rtdVoltageValue); + // activeSerial->print("*"); + previousMillis = millis(); - // Apply configuration twice (didn't seem to stick unless we did) - AD5940_HSLoopCfgS(&HsLoopCfg); - AD5940_HSLoopCfgS(&HsLoopCfg); + // Check for "ERROR: AD5940 wakeup timeout" + if (-1000.0f == rtd_res) + { + // In case of an error, send all 0's + initSinglePacketToDefault(); + } + else + { + singleSensorPacket.impFreq = storedFrequency; // Impedance Frequency + singleSensorPacket.impDataPoints = 1; // Impedance Data Points. Hard coded to 1 + singleSensorPacket.impRzMag = medianMag; // Value of medianMag + singleSensorPacket.impRzPhase = medianPhase; // Value of medianPhase + singleSensorPacket.rtdFreq = 0; // RTD Frequency. Hard coded to 0.0 + singleSensorPacket.rtdDataPoints = 1; // Impedance Data Points. Hard coded to 1 + singleSensorPacket.rtdRzMag = rtd_res; // Value of rtd_resistance + singleSensorPacket.rtdRzPhase = 0.0; // RTD Rz Phase. Hard coded to 0.0 + } + activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); +} - // Configure ADC - dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N; - dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P; - dsp_cfg.ADCBaseCfg.ADCPga = ADCPGA_1; +float getRTDMeasurements(float sensor_mV) +{ + AFERefCfg_Type aferef_cfg; + HSLoopCfg_Type HsLoopCfg; + DSPCfg_Type dsp_cfg; - dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16; - dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ; - dsp_cfg.ADCFilterCfg.ADCSinc2Osr = ADCSINC2OSR_44; - dsp_cfg.ADCFilterCfg.ADCSinc3Osr = ADCSINC3OSR_4; - dsp_cfg.ADCFilterCfg.BpNotch = bTRUE; - dsp_cfg.ADCFilterCfg.BpSinc3 = bTRUE; - dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE; + uint32_t adcCode_rtd, adcCode_ref; + float volt_rtd, volt_ref; + float rtd_resistance; + const float RtdRefRes = REF_RESISTOR_VALUE; - AD5940_DSPCfgS(&dsp_cfg); + // Wake up the AD5940 from low power mode + if (AD5940_WakeUp(10) > 10) + { + // activeSerial->println("ERROR: AD5940 wakeup timeout"); + return -1000.0f; + } - // Enable AFE blocks - AD5940_AFECtrlS(AFECTRL_HSTIAPWR | AFECTRL_INAMPPWR | AFECTRL_EXTBUFPWR | AFECTRL_WG | AFECTRL_DACREFPWR | AFECTRL_HSDACPWR | AFECTRL_SINC2NOTCH | AFECTRL_ADCPWR, - bTRUE); + // Reset LPDAC configuration before RTD measurement + LPDACCfg_Type lpdac_reset = {0}; + lpdac_reset.PowerEn = bFALSE; + AD5940_LPDACCfgS(&lpdac_reset); - // Restart waveform generator with proper sequence - AD5940_AFECtrlS(AFECTRL_WG, bFALSE); - AD5940_Delay10us(1000); // 10ms settling - AD5940_AFECtrlS(AFECTRL_WG, bTRUE); + // Configure High-Speed Loop + HsLoopCfg.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2; + HsLoopCfg.HsDacCfg.HsDacGain = HSDACGAIN_1; + HsLoopCfg.HsDacCfg.HsDacUpdateRate = 7; - // Extended settling time for RTD measurement - AD5940_Delay10us(500); // 5ms settling time + // TIA settings + HsLoopCfg.HsTiaCfg.DiodeClose = bFALSE; + HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1; + HsLoopCfg.HsTiaCfg.HstiaCtia = 32; + HsLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN; + HsLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN; + HsLoopCfg.HsTiaCfg.HstiaRtiaSel = RTD_RTIA; - // Sample RTD with improved averaging - sampleADC(1); - uint64_t accRTD = 0; - for (uint32_t i = 0; i < NUM_RTD_SAMPLES; ++i) - { - accRTD += sampleADC(1); // Increased sampling delay + // Switch matrix for RTD measurement + HsLoopCfg.SWMatCfg.Dswitch = RTD_DSWITCH; + HsLoopCfg.SWMatCfg.Pswitch = RTD_PSWITCH; + HsLoopCfg.SWMatCfg.Nswitch = RTD_NSWITCH; + HsLoopCfg.SWMatCfg.Tswitch = RTD_TSWITCH; - AD5940_Delay10us(10); // Small delay between samples - } - adcCode_rtd = accRTD / NUM_RTD_SAMPLES; + // Configure waveform generator + HsLoopCfg.WgCfg.WgType = WGTYPE_MMR; + HsLoopCfg.WgCfg.GainCalEn = bFALSE; + HsLoopCfg.WgCfg.OffsetCalEn = bFALSE; + uint32_t code = mV_to_WgCode(sensor_mV); + HsLoopCfg.WgCfg.WgCode = code; - // Reconfigure switch matrix for reference resistor - HsLoopCfg.SWMatCfg.Dswitch = SWD_RCAL0; - HsLoopCfg.SWMatCfg.Pswitch = SWP_RCAL0; - HsLoopCfg.SWMatCfg.Nswitch = SWN_RCAL1; - HsLoopCfg.SWMatCfg.Tswitch = SWT_RCAL1 | SWT_TRTIA; + // Apply configuration twice (didn't seem to stick unless we did) + AD5940_HSLoopCfgS(&HsLoopCfg); + AD5940_HSLoopCfgS(&HsLoopCfg); - // Apply new switch configuration - AD5940_SWMatrixCfgS(&HsLoopCfg.SWMatCfg); + // Configure ADC + dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N; + dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P; + dsp_cfg.ADCBaseCfg.ADCPga = ADCPGA_1; - // Additional settling time after switch change - AD5940_Delay10us(500); // 5ms settling - sampleADC(1); - // Sample reference resistor - uint64_t accREF = 0; - for (uint32_t i = 0; i < NUM_RTD_SAMPLES; ++i) - { - accREF += sampleADC(1); - AD5940_Delay10us(10); - } - adcCode_ref = accREF / NUM_RTD_SAMPLES; + dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16; + dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ; + dsp_cfg.ADCFilterCfg.ADCSinc2Osr = ADCSINC2OSR_44; + dsp_cfg.ADCFilterCfg.ADCSinc3Osr = ADCSINC3OSR_4; + dsp_cfg.ADCFilterCfg.BpNotch = bTRUE; + dsp_cfg.ADCFilterCfg.BpSinc3 = bTRUE; + dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE; - // reset switch matrix - resetSwitchMatrix(); + AD5940_DSPCfgS(&dsp_cfg); - // Disable all AFE blocks that were enabled - AD5940_AFECtrlS(AFECTRL_HSTIAPWR | AFECTRL_INAMPPWR | AFECTRL_EXTBUFPWR | AFECTRL_WG | AFECTRL_DACREFPWR | AFECTRL_HSDACPWR | AFECTRL_SINC2NOTCH | AFECTRL_ADCPWR, bFALSE); + // Enable AFE blocks + AD5940_AFECtrlS(AFECTRL_HSTIAPWR | AFECTRL_INAMPPWR | AFECTRL_EXTBUFPWR | AFECTRL_WG | AFECTRL_DACREFPWR | AFECTRL_HSDACPWR | AFECTRL_SINC2NOTCH | AFECTRL_ADCPWR, + bTRUE); - // Convert to voltages - volt_ref = AD5940_ADCCode2Volt(adcCode_ref, ADCPGA_1, 1.82); - volt_rtd = AD5940_ADCCode2Volt(adcCode_rtd, ADCPGA_1, 1.82); + // Restart waveform generator with proper sequence + AD5940_AFECtrlS(AFECTRL_WG, bFALSE); + AD5940_Delay10us(1000); // 10ms settling + AD5940_AFECtrlS(AFECTRL_WG, bTRUE); - // Calculate resistance - rtd_resistance = RtdRefRes * (volt_ref / volt_rtd); + // Extended settling time for RTD measurement + AD5940_Delay10us(500); // 5ms settling time - // Verbose output - if (verboseMode) - { - activeSerial->println(" "); + // Sample RTD with improved averaging + sampleADC(1); + uint64_t accRTD = 0; + for (uint32_t i = 0; i < NUM_RTD_SAMPLES; ++i) + { + accRTD += sampleADC(1); // Increased sampling delay - // activeSerial->println("RTD Measurement"); - // activeSerial->print(" RCal Averaged Measurement: "); - activeSerial->println(adcCode_ref); - // activeSerial->print(" RTD Averaged Measurement: "); - activeSerial->println(adcCode_rtd); - // activeSerial->printf(" NUM_SAMPLES: %u", NUM_RTD_SAMPLES); - activeSerial->println(" "); - // activeSerial->print(" RTD TIA Resistor: "); - switch (RTD_RTIA) - { - case HSTIARTIA_200: - // activeSerial->println("200 Ohm"); - break; - case HSTIARTIA_1K: - // activeSerial->println("1K Ohm"); - break; - case HSTIARTIA_5K: - // activeSerial->println("5K Ohm"); - break; - case HSTIARTIA_10K: - // activeSerial->println("10K Ohm"); - break; - case HSTIARTIA_20K: - // activeSerial->println("20K Ohm"); - break; - case HSTIARTIA_40K: - // activeSerial->println("40K Ohm"); - break; - case HSTIARTIA_80K: - // activeSerial->println("80K Ohm"); - break; - case HSTIARTIA_160K: - // activeSerial->println("160K Ohm"); - break; - default: - // activeSerial->println("Unknown"); - break; - } - } - return rtd_resistance; + AD5940_Delay10us(10); // Small delay between samples } + adcCode_rtd = accRTD / NUM_RTD_SAMPLES; - void updateEEPROMdata(String command) + // Reconfigure switch matrix for reference resistor + HsLoopCfg.SWMatCfg.Dswitch = SWD_RCAL0; + HsLoopCfg.SWMatCfg.Pswitch = SWP_RCAL0; + HsLoopCfg.SWMatCfg.Nswitch = SWN_RCAL1; + HsLoopCfg.SWMatCfg.Tswitch = SWT_RCAL1 | SWT_TRTIA; + + // Apply new switch configuration + AD5940_SWMatrixCfgS(&HsLoopCfg.SWMatCfg); + + // Additional settling time after switch change + AD5940_Delay10us(500); // 5ms settling + sampleADC(1); + // Sample reference resistor + uint64_t accREF = 0; + for (uint32_t i = 0; i < NUM_RTD_SAMPLES; ++i) { - updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; - int firstComma = command.indexOf(','); - if (firstComma < 0) + accREF += sampleADC(1); + AD5940_Delay10us(10); + } + adcCode_ref = accREF / NUM_RTD_SAMPLES; + + // reset switch matrix + resetSwitchMatrix(); + + // Disable all AFE blocks that were enabled + AD5940_AFECtrlS(AFECTRL_HSTIAPWR | AFECTRL_INAMPPWR | AFECTRL_EXTBUFPWR | AFECTRL_WG | AFECTRL_DACREFPWR | AFECTRL_HSDACPWR | AFECTRL_SINC2NOTCH | AFECTRL_ADCPWR, bFALSE); + + // Convert to voltages + volt_ref = AD5940_ADCCode2Volt(adcCode_ref, ADCPGA_1, 1.82); + volt_rtd = AD5940_ADCCode2Volt(adcCode_rtd, ADCPGA_1, 1.82); + + // Calculate resistance + rtd_resistance = RtdRefRes * (volt_ref / volt_rtd); + + // Verbose output + if (verboseMode) + { + activeSerial->println(" "); + + // activeSerial->println("RTD Measurement"); + // activeSerial->print(" RCal Averaged Measurement: "); + activeSerial->println(adcCode_ref); + // activeSerial->print(" RTD Averaged Measurement: "); + activeSerial->println(adcCode_rtd); + // activeSerial->printf(" NUM_SAMPLES: %u", NUM_RTD_SAMPLES); + activeSerial->println(" "); + // activeSerial->print(" RTD TIA Resistor: "); + switch (RTD_RTIA) { - updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_CMD; - // activeSerial->println("Error: Invalid save command format"); - return; + case HSTIARTIA_200: + // activeSerial->println("200 Ohm"); + break; + case HSTIARTIA_1K: + // activeSerial->println("1K Ohm"); + break; + case HSTIARTIA_5K: + // activeSerial->println("5K Ohm"); + break; + case HSTIARTIA_10K: + // activeSerial->println("10K Ohm"); + break; + case HSTIARTIA_20K: + // activeSerial->println("20K Ohm"); + break; + case HSTIARTIA_40K: + // activeSerial->println("40K Ohm"); + break; + case HSTIARTIA_80K: + // activeSerial->println("80K Ohm"); + break; + case HSTIARTIA_160K: + // activeSerial->println("160K Ohm"); + break; + default: + // activeSerial->println("Unknown"); + break; } - String dataStr = command.substring(firstComma + 1); + } + return rtd_resistance; +} - // Calculate maximum values we can store in AT25010B (128 bytes) - // DOUBLE_COUNT * 8 + float_count * 4 <= 128 - int maxFloats = (128 - (DOUBLE_COUNT * 8)) / 4; - int maxTotal = DOUBLE_COUNT + maxFloats; +void updateEEPROMdata(String command) +{ + updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; + int firstComma = command.indexOf(','); + if (firstComma < 0) + { + updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_CMD; + // activeSerial->println("Error: Invalid save command format"); + return; + } + String dataStr = command.substring(firstComma + 1); - double doubleValues[DOUBLE_COUNT]; - float floatValues[maxFloats]; - int valueIndex = 0; + // Calculate maximum values we can store in AT25010B (128 bytes) + // DOUBLE_COUNT * 8 + float_count * 4 <= 128 + int maxFloats = (128 - (DOUBLE_COUNT * 8)) / 4; + int maxTotal = DOUBLE_COUNT + maxFloats; - // Parse values - while (valueIndex < maxTotal && dataStr.length() > 0) + double doubleValues[DOUBLE_COUNT]; + float floatValues[maxFloats]; + int valueIndex = 0; + + // Parse values + while (valueIndex < maxTotal && dataStr.length() > 0) + { + int commaPos = dataStr.indexOf(','); + String valueStr; + if (commaPos >= 0) { - int commaPos = dataStr.indexOf(','); - String valueStr; - if (commaPos >= 0) + valueStr = dataStr.substring(0, commaPos); + dataStr = dataStr.substring(commaPos + 1); + } + else + { + // Last value + valueStr = dataStr; + dataStr = ""; // Clear dataStr to end the loop + } + + // Convert string and store in appropriate array + if (valueStr.length() > 0) + { + if (valueIndex < DOUBLE_COUNT) { - valueStr = dataStr.substring(0, commaPos); - dataStr = dataStr.substring(commaPos + 1); + // Store as double + doubleValues[valueIndex] = strtod(valueStr.c_str(), NULL); } else { - // Last value - valueStr = dataStr; - dataStr = ""; // Clear dataStr to end the loop + // Store as float + floatValues[valueIndex - DOUBLE_COUNT] = strtof(valueStr.c_str(), NULL); } - - // Convert string and store in appropriate array - if (valueStr.length() > 0) - { - if (valueIndex < DOUBLE_COUNT) - { - // Store as double - doubleValues[valueIndex] = strtod(valueStr.c_str(), NULL); - } - else - { - // Store as float - floatValues[valueIndex - DOUBLE_COUNT] = strtof(valueStr.c_str(), NULL); - } - valueIndex++; - } + valueIndex++; } + } - // Check if we got at least 1 value - if (valueIndex == 0) - { - // activeSerial->println("Error: No valid values found"); - updateEepromStatus = UPDATE_EEPROM_STATUS_NO_VALID_VALUES; - return; - } - if (valueIndex > maxTotal) - { - updateEepromStatus = UPDATE_EEPROM_STATUS_TOO_MANY_VALUES; - return; - } + // Check if we got at least 1 value + if (valueIndex == 0) + { + // activeSerial->println("Error: No valid values found"); + updateEepromStatus = UPDATE_EEPROM_STATUS_NO_VALID_VALUES; + return; + } + if (valueIndex > maxTotal) + { + updateEepromStatus = UPDATE_EEPROM_STATUS_TOO_MANY_VALUES; + return; + } - int doubleCount = min(valueIndex, DOUBLE_COUNT); - int floatCount = max(0, valueIndex - DOUBLE_COUNT); + int doubleCount = min(valueIndex, DOUBLE_COUNT); + int floatCount = max(0, valueIndex - DOUBLE_COUNT); - unsigned int baseAddress = 0; - writeMixedValues(baseAddress, doubleValues, doubleCount, floatValues, floatCount); - // activeSerial->println("save attempted"); + unsigned int baseAddress = 0; + writeMixedValues(baseAddress, doubleValues, doubleCount, floatValues, floatCount); + // activeSerial->println("save attempted"); - // Read back the values to confirm they were written correctly - double readDoubles[DOUBLE_COUNT]; - float readFloats[maxFloats]; - readMixedValues(baseAddress, readDoubles, doubleCount, readFloats, floatCount); + // Read back the values to confirm they were written correctly + double readDoubles[DOUBLE_COUNT]; + float readFloats[maxFloats]; + readMixedValues(baseAddress, readDoubles, doubleCount, readFloats, floatCount); - // activeSerial->println("Verification - Values read back from EEPROM:"); - bool DoubleVerificationSuccess = true; - bool FloatVerificationSuccess = true; + // activeSerial->println("Verification - Values read back from EEPROM:"); + bool DoubleVerificationSuccess = true; + bool FloatVerificationSuccess = true; - // Verify doubles - for (int i = 0; i < doubleCount; i++) + // Verify doubles + for (int i = 0; i < doubleCount; i++) + { + // activeSerial->print(i); + // activeSerial->print(" (double): "); + // activeSerial->println(readDoubles[i], 10); + if (abs(doubleValues[i] - readDoubles[i]) > 0.000000001) { + DoubleVerificationSuccess = false; + break; + // activeSerial->print("Warning: Double value "); // activeSerial->print(i); - // activeSerial->print(" (double): "); - // activeSerial->println(readDoubles[i], 10); - if (abs(doubleValues[i] - readDoubles[i]) > 0.000000001) - { - DoubleVerificationSuccess = false; - break; - // activeSerial->print("Warning: Double value "); - // activeSerial->print(i); - // activeSerial->println(" does not match exactly what was written"); - } + // activeSerial->println(" does not match exactly what was written"); } + } - // Verify floats - for (int i = 0; i < floatCount; i++) + // Verify floats + for (int i = 0; i < floatCount; i++) + { + // activeSerial->print(i + DOUBLE_COUNT); + // activeSerial->print(" (float): "); + // activeSerial->println(readFloats[i], 6); + if (abs(floatValues[i] - readFloats[i]) > 0.000001) { + FloatVerificationSuccess = false; + break; + // activeSerial->print("Warning: Float value "); // activeSerial->print(i + DOUBLE_COUNT); - // activeSerial->print(" (float): "); - // activeSerial->println(readFloats[i], 6); - if (abs(floatValues[i] - readFloats[i]) > 0.000001) - { - FloatVerificationSuccess = false; - break; - // activeSerial->print("Warning: Float value "); - // activeSerial->print(i + DOUBLE_COUNT); - // activeSerial->println(" does not match exactly what was written"); - } + // activeSerial->println(" does not match exactly what was written"); } - - if (DoubleVerificationSuccess && FloatVerificationSuccess) - { - updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; - // activeSerial->println("Verification successful: All values match!"); - } - else - { - updateEepromStatus = UPDATE_EEPROM_STATUS_VALUES_VERIFICATION_FAILED; - } } - void getEEPROMdata(void) + if (DoubleVerificationSuccess && FloatVerificationSuccess) { - unsigned int baseAddress = 0; // Same address used in save + updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; + // activeSerial->println("Verification successful: All values match!"); + } + else + { + updateEepromStatus = UPDATE_EEPROM_STATUS_VALUES_VERIFICATION_FAILED; + } +} - // Calculate maximum values we can store - int maxFloats = (128 - (DOUBLE_COUNT * 8)) / 4; +void getEEPROMdata(void) +{ + unsigned int baseAddress = 0; // Same address used in save - double doubleValues[DOUBLE_COUNT]; - float floatValues[maxFloats]; + // Calculate maximum values we can store + int maxFloats = (128 - (DOUBLE_COUNT * 8)) / 4; - readMixedValues(baseAddress, doubleValues, DOUBLE_COUNT, floatValues, maxFloats); + double doubleValues[DOUBLE_COUNT]; + float floatValues[maxFloats]; - // Display doubles - for (int i = 0; i < DOUBLE_COUNT; i++) - { - eepromDataPacket.doubleValue[i] = doubleValues[i]; - } + readMixedValues(baseAddress, doubleValues, DOUBLE_COUNT, floatValues, maxFloats); - // Display floats - for (int i = 0; i < maxFloats; i++) - { - eepromDataPacket.floatValue[i] = floatValues[i]; - } - - activeSerial->write((uint8_t *)&eepromDataPacket, sizeof(eepromDataPacket)); + // Display doubles + for (int i = 0; i < DOUBLE_COUNT; i++) + { + eepromDataPacket.doubleValue[i] = doubleValues[i]; } - void handleMstCommand(String cmd) + // Display floats + for (int i = 0; i < maxFloats; i++) { - // Check if the first 4 characters are "mst," - if (cmd.startsWith("mst,")) - { - // Remove "mst," prefix - String dataPart = cmd.substring(4); + eepromDataPacket.floatValue[i] = floatValues[i]; + } - // Split by comma - int idx = 0; - int start = 0; - int end = 0; + activeSerial->write((uint8_t *)&eepromDataPacket, sizeof(eepromDataPacket)); +} - while (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX && start < dataPart.length()) - { - end = dataPart.indexOf(',', start); - if (end == -1) - end = dataPart.length(); // Last value +void handleMstCommand(String cmd) +{ + // Check if the first 4 characters are "mst," + if (cmd.startsWith("mst,")) + { + // Remove "mst," prefix + String dataPart = cmd.substring(4); - String update_param = "mst,"; - String token = dataPart.substring(start, end); + // Split by comma + int idx = 0; + int start = 0; + int end = 0; - // Assign to tempSettings - switch (idx) - { - case CONDUCTIVITY_MST_PARAM_IDX_SINFREQ: - tempSettings.SinFreq = token.toFloat(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.SinFreq, 4); - break; + while (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX && start < dataPart.length()) + { + end = dataPart.indexOf(',', start); + if (end == -1) + end = dataPart.length(); // Last value - case CONDUCTIVITY_MST_PARAM_IDX_DACPP: - tempSettings.DacVoltPP = token.toFloat(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.DacVoltPP, 4); - break; + String update_param = "mst,"; + String token = dataPart.substring(start, end); - case CONDUCTIVITY_MST_PARAM_IDX_BIAS: - tempSettings.BiasVolt = token.toFloat(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.BiasVolt, 4); - break; + // Assign to tempSettings + switch (idx) + { + case CONDUCTIVITY_MST_PARAM_IDX_SINFREQ: + tempSettings.SinFreq = token.toFloat(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.SinFreq, 4); + break; - case CONDUCTIVITY_MST_PARAM_IDX_RTIA: - tempSettings.HstiaRtiaSel = token.toInt(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.HstiaRtiaSel); - break; + case CONDUCTIVITY_MST_PARAM_IDX_DACPP: + tempSettings.DacVoltPP = token.toFloat(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.DacVoltPP, 4); + break; - case CONDUCTIVITY_MST_PARAM_IDX_PGA: - tempSettings.AdcPgaGain = token.toInt(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.AdcPgaGain); - break; + case CONDUCTIVITY_MST_PARAM_IDX_BIAS: + tempSettings.BiasVolt = token.toFloat(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.BiasVolt, 4); + break; - case CONDUCTIVITY_MST_PARAM_IDX_DFTNUM: - tempSettings.DftNum = token.toInt(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.DftNum); - break; + case CONDUCTIVITY_MST_PARAM_IDX_RTIA: + tempSettings.HstiaRtiaSel = token.toInt(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.HstiaRtiaSel); + break; - case CONDUCTIVITY_MST_PARAM_IDX_AVGNUM: - tempSettings.ADCAvgNum = token.toInt(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.ADCAvgNum); - break; - } + case CONDUCTIVITY_MST_PARAM_IDX_PGA: + tempSettings.AdcPgaGain = token.toInt(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.AdcPgaGain); + break; - // Call handleMstCommand for this parameter - updateMeasurementSettings(update_param, idx); + case CONDUCTIVITY_MST_PARAM_IDX_DFTNUM: + tempSettings.DftNum = token.toInt(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.DftNum); + break; - start = end + 1; - idx++; + case CONDUCTIVITY_MST_PARAM_IDX_AVGNUM: + tempSettings.ADCAvgNum = token.toInt(); + update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.ADCAvgNum); + break; } + + // Call handleMstCommand for this parameter + updateMeasurementSettings(update_param, idx); + + start = end + 1; + idx++; } } +} - void updateMeasurementSettings(String cmd, uint8_t idx) +void updateMeasurementSettings(String cmd, uint8_t idx) +{ + if ((idx >= CONDUCTIVITY_MST_PARAM_IDX_SINFREQ) && (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX)) { - if ((idx >= CONDUCTIVITY_MST_PARAM_IDX_SINFREQ) && (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX)) - { - updateCfgStatus[idx] = UPDATE_CFG_STATUS_SUCCESS; - } - else - { - return; - } + updateCfgStatus[idx] = UPDATE_CFG_STATUS_SUCCESS; + } + else + { + return; + } - // Command format: cfg,parameter,value - // Examples: - // - cfg,sinfreq,1000.0 (Set sine wave frequency to 1000 Hz) + // Command format: cfg,parameter,value + // Examples: + // - cfg,sinfreq,1000.0 (Set sine wave frequency to 1000 Hz) - // Array to hold parsed command parts - String params[3]; - int paramIndex = 0; - int startIndex = 0; + // Array to hold parsed command parts + String params[3]; + int paramIndex = 0; + int startIndex = 0; - // Parse command string using comma delimiter - for (uint i = 0; i < cmd.length(); i++) + // Parse command string using comma delimiter + for (uint i = 0; i < cmd.length(); i++) + { + if (cmd.charAt(i) == ',') { - if (cmd.charAt(i) == ',') - { - params[paramIndex] = cmd.substring(startIndex, i); - startIndex = i + 1; - paramIndex++; + params[paramIndex] = cmd.substring(startIndex, i); + startIndex = i + 1; + paramIndex++; - // Safety check to prevent array overflow - if (paramIndex >= 3) - break; - } + // Safety check to prevent array overflow + if (paramIndex >= 3) + break; } + } - // Get last parameter (after the last comma) - if (paramIndex < 3) - { - params[paramIndex] = cmd.substring(startIndex); - } + // Get last parameter (after the last comma) + if (paramIndex < 3) + { + params[paramIndex] = cmd.substring(startIndex); + } - // Get configuration structure pointer - AppIMPCfg_Type *pImpedanceCfg; - AppIMPGetCfg(&pImpedanceCfg); + // Get configuration structure pointer + AppIMPCfg_Type *pImpedanceCfg; + AppIMPGetCfg(&pImpedanceCfg); - // Extract parameter name and value - String param = params[1]; - String value = params[2]; + // Extract parameter name and value + String param = params[1]; + String value = params[2]; - // Handle special commands for saving/recalling configurations - if (param == "save") - { - saveCurrentConfig(); - // activeSerial->println("Configuration saved"); - return; - } - else if (param == "recall") - { - recallSavedConfig(); - // activeSerial->println("Configuration recalled"); - return; - } + // Handle special commands for saving/recalling configurations + if (param == "save") + { + saveCurrentConfig(); + // activeSerial->println("Configuration saved"); + return; + } + else if (param == "recall") + { + recallSavedConfig(); + // activeSerial->println("Configuration recalled"); + return; + } - // Process different configuration parameters - if (param == "sinfreq") - { - // Set sine wave frequency (Hz) - pImpedanceCfg->SinFreq = value.toFloat(); - // activeSerial->printf("Set SinFreq to: %.2f Hz\n", pImpedanceCfg->SinFreq); - } - else if (param == "dacpp") - { - // Set DAC peak-to-peak voltage (mV) - pImpedanceCfg->DacVoltPP = value.toFloat(); - // activeSerial->printf("Set DacVoltPP to: %.2f mV\n", pImpedanceCfg->DacVoltPP); - } - else if (param == "bias") - { - // Set DC bias voltage (mV) - pImpedanceCfg->BiasVolt = value.toFloat(); - // activeSerial->printf("Set BiasVolt to: %.2f mV\n", pImpedanceCfg->BiasVolt); - } - else if (param == "rtia") - { - // Set TIA (Transimpedance Amplifier) feedback resistor value - uint32_t rtia = DEFAULT_RTIA; // default value - int valueTest = value.toInt(); - // activeSerial->print("Value:"); - // activeSerial->println(value); - // Map string values to corresponding constants - if (valueTest == 0) - rtia = HSTIARTIA_200; - else if (valueTest == 1) - rtia = HSTIARTIA_1K; - else if (valueTest == 2) - rtia = HSTIARTIA_5K; - else if (valueTest == 3) - rtia = HSTIARTIA_10K; - else if (valueTest == 4) - rtia = HSTIARTIA_20K; - else if (valueTest == 5) - rtia = HSTIARTIA_40K; - else if (valueTest == 6) - rtia = HSTIARTIA_80K; - else if (valueTest == 7) - rtia = HSTIARTIA_160K; - else - updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_TIA; - // activeSerial->print("no change to tia"); + // Process different configuration parameters + if (param == "sinfreq") + { + // Set sine wave frequency (Hz) + pImpedanceCfg->SinFreq = value.toFloat(); + // activeSerial->printf("Set SinFreq to: %.2f Hz\n", pImpedanceCfg->SinFreq); + } + else if (param == "dacpp") + { + // Set DAC peak-to-peak voltage (mV) + pImpedanceCfg->DacVoltPP = value.toFloat(); + // activeSerial->printf("Set DacVoltPP to: %.2f mV\n", pImpedanceCfg->DacVoltPP); + } + else if (param == "bias") + { + // Set DC bias voltage (mV) + pImpedanceCfg->BiasVolt = value.toFloat(); + // activeSerial->printf("Set BiasVolt to: %.2f mV\n", pImpedanceCfg->BiasVolt); + } + else if (param == "rtia") + { + // Set TIA (Transimpedance Amplifier) feedback resistor value + uint32_t rtia = DEFAULT_RTIA; // default value + int valueTest = value.toInt(); + // activeSerial->print("Value:"); + // activeSerial->println(value); + // Map string values to corresponding constants + if (valueTest == 0) + rtia = HSTIARTIA_200; + else if (valueTest == 1) + rtia = HSTIARTIA_1K; + else if (valueTest == 2) + rtia = HSTIARTIA_5K; + else if (valueTest == 3) + rtia = HSTIARTIA_10K; + else if (valueTest == 4) + rtia = HSTIARTIA_20K; + else if (valueTest == 5) + rtia = HSTIARTIA_40K; + else if (valueTest == 6) + rtia = HSTIARTIA_80K; + else if (valueTest == 7) + rtia = HSTIARTIA_160K; + else + updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_TIA; + // activeSerial->print("no change to tia"); - pImpedanceCfg->HstiaRtiaSel = rtia; - // activeSerial->printf("Set RTIA to: %s\n", value.c_str()); - currentTIA = rtia; - // activeSerial->print("currentTIA: "); - // activeSerial->println(currentTIA); - } - else if (param == "pga") - { - // Set ADC Programmable Gain Amplifier gain - uint32_t pga = ADCPGA_1; // default value (1x gain) + pImpedanceCfg->HstiaRtiaSel = rtia; + // activeSerial->printf("Set RTIA to: %s\n", value.c_str()); + currentTIA = rtia; + // activeSerial->print("currentTIA: "); + // activeSerial->println(currentTIA); + } + else if (param == "pga") + { + // Set ADC Programmable Gain Amplifier gain + uint32_t pga = ADCPGA_1; // default value (1x gain) - // Map string values to corresponding constants - if (value == "1") - pga = ADCPGA_1; - else if (value == "1.5") - pga = ADCPGA_1P5; - else if (value == "2") - pga = ADCPGA_2; - else if (value == "4") - pga = ADCPGA_4; - else if (value == "9") - pga = ADCPGA_9; - else - updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_PGA; + // Map string values to corresponding constants + if (value == "1") + pga = ADCPGA_1; + else if (value == "1.5") + pga = ADCPGA_1P5; + else if (value == "2") + pga = ADCPGA_2; + else if (value == "4") + pga = ADCPGA_4; + else if (value == "9") + pga = ADCPGA_9; + else + updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_PGA; - pImpedanceCfg->AdcPgaGain = pga; - // activeSerial->printf("Set PGA gain to: %s\n", value.c_str()); - } - else if (param == "dftnum") - { - // Set DFT (Discrete Fourier Transform) number of points - uint32_t dft = DFTNUM_4096; // default value (4096 points) + pImpedanceCfg->AdcPgaGain = pga; + // activeSerial->printf("Set PGA gain to: %s\n", value.c_str()); + } + else if (param == "dftnum") + { + // Set DFT (Discrete Fourier Transform) number of points + uint32_t dft = DFTNUM_4096; // default value (4096 points) - // Map string values to corresponding constants - if (value == "4096") - dft = DFTNUM_4096; - else if (value == "2048") - dft = DFTNUM_2048; - else if (value == "1024") - dft = DFTNUM_1024; - else if (value == "512") - dft = DFTNUM_512; - else if (value == "256") - dft = DFTNUM_256; - else - updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_DFT_NUM; + // Map string values to corresponding constants + if (value == "4096") + dft = DFTNUM_4096; + else if (value == "2048") + dft = DFTNUM_2048; + else if (value == "1024") + dft = DFTNUM_1024; + else if (value == "512") + dft = DFTNUM_512; + else if (value == "256") + dft = DFTNUM_256; + else + updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_DFT_NUM; - pImpedanceCfg->DftNum = dft; - // activeSerial->printf("Set DFT number to: %s\n", value.c_str()); - } - else if (param == "avgnum") - { - // Set ADC averaging number (how many samples to average) - uint32_t avg = ADCAVGNUM_16; // default value (16 samples) + pImpedanceCfg->DftNum = dft; + // activeSerial->printf("Set DFT number to: %s\n", value.c_str()); + } + else if (param == "avgnum") + { + // Set ADC averaging number (how many samples to average) + uint32_t avg = ADCAVGNUM_16; // default value (16 samples) - // Map string values to corresponding constants - if (value == "2") - avg = ADCAVGNUM_2; - else if (value == "4") - avg = ADCAVGNUM_4; - else if (value == "8") - avg = ADCAVGNUM_8; - else if (value == "16") - avg = ADCAVGNUM_16; - else - updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_AVG_NUM; - - pImpedanceCfg->ADCAvgNum = avg; - // activeSerial->printf("Set ADC average number to: %s\n", value.c_str()); - } - else if (param == "sweep") - { - // Enable/disable frequency sweep mode - bool enableSweep = (value == "1" || value.equalsIgnoreCase("true")); - pImpedanceCfg->SweepCfg.SweepEn = enableSweep ? bTRUE : bFALSE; - // activeSerial->printf("Set sweep enable to: %d\n", pImpedanceCfg->SweepCfg.SweepEn); - } - else if (param == "sweepstart") - { - // Set sweep start frequency (Hz) - pImpedanceCfg->SweepCfg.SweepStart = value.toFloat(); - // activeSerial->printf("Set sweep start frequency to: %.2f Hz\n", pImpedanceCfg->SweepCfg.SweepStart); - } - else if (param == "sweepstop") - { - // Set sweep stop frequency (Hz) - pImpedanceCfg->SweepCfg.SweepStop = value.toFloat(); - // activeSerial->printf("Set sweep stop frequency to: %.2f Hz\n", pImpedanceCfg->SweepCfg.SweepStop); - } - else if (param == "sweeppoints") - { - // Set number of frequency points in the sweep - pImpedanceCfg->SweepCfg.SweepPoints = value.toInt(); - // activeSerial->printf("Set sweep points to: %d\n", pImpedanceCfg->SweepCfg.SweepPoints); - } - else if (param == "sweeplog") - { - // Set logarithmic (true) or linear (false) frequency spacing - bool logSpacing = (value == "1" || value.equalsIgnoreCase("true")); - pImpedanceCfg->SweepCfg.SweepLog = logSpacing ? bTRUE : bFALSE; - // activeSerial->printf("Set sweep log mode to: %d\n", pImpedanceCfg->SweepCfg.SweepLog); - } + // Map string values to corresponding constants + if (value == "2") + avg = ADCAVGNUM_2; + else if (value == "4") + avg = ADCAVGNUM_4; + else if (value == "8") + avg = ADCAVGNUM_8; + else if (value == "16") + avg = ADCAVGNUM_16; else - { - // Handle unrecognized parameter - // activeSerial->println("Malformed command: unrecognized parameter"); - updateCfgStatus[idx] = UPDATE_CFG_STATUS_ERR_UNRECOGNIZED_PARAM; - return; - } + updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_AVG_NUM; - // Mark that parameters have been changed and need to be applied - pImpedanceCfg->bParaChanged = bTRUE; - - // Automatically save the configuration after any successful change - saveCurrentConfig(); + pImpedanceCfg->ADCAvgNum = avg; + // activeSerial->printf("Set ADC average number to: %s\n", value.c_str()); } - - void getMesaurementSettings(void) + else if (param == "sweep") { - // Pointer to store configuration structure - AppIMPCfg_Type *cfg; + // Enable/disable frequency sweep mode + bool enableSweep = (value == "1" || value.equalsIgnoreCase("true")); + pImpedanceCfg->SweepCfg.SweepEn = enableSweep ? bTRUE : bFALSE; + // activeSerial->printf("Set sweep enable to: %d\n", pImpedanceCfg->SweepCfg.SweepEn); + } + else if (param == "sweepstart") + { + // Set sweep start frequency (Hz) + pImpedanceCfg->SweepCfg.SweepStart = value.toFloat(); + // activeSerial->printf("Set sweep start frequency to: %.2f Hz\n", pImpedanceCfg->SweepCfg.SweepStart); + } + else if (param == "sweepstop") + { + // Set sweep stop frequency (Hz) + pImpedanceCfg->SweepCfg.SweepStop = value.toFloat(); + // activeSerial->printf("Set sweep stop frequency to: %.2f Hz\n", pImpedanceCfg->SweepCfg.SweepStop); + } + else if (param == "sweeppoints") + { + // Set number of frequency points in the sweep + pImpedanceCfg->SweepCfg.SweepPoints = value.toInt(); + // activeSerial->printf("Set sweep points to: %d\n", pImpedanceCfg->SweepCfg.SweepPoints); + } + else if (param == "sweeplog") + { + // Set logarithmic (true) or linear (false) frequency spacing + bool logSpacing = (value == "1" || value.equalsIgnoreCase("true")); + pImpedanceCfg->SweepCfg.SweepLog = logSpacing ? bTRUE : bFALSE; + // activeSerial->printf("Set sweep log mode to: %d\n", pImpedanceCfg->SweepCfg.SweepLog); + } + else + { + // Handle unrecognized parameter + // activeSerial->println("Malformed command: unrecognized parameter"); + updateCfgStatus[idx] = UPDATE_CFG_STATUS_ERR_UNRECOGNIZED_PARAM; + return; + } - // Get the current impedance measurement configuration - AppIMPGetCfg(&cfg); + // Mark that parameters have been changed and need to be applied + pImpedanceCfg->bParaChanged = bTRUE; - measurementSettingsPacket.SinFreq = cfg->SinFreq; - measurementSettingsPacket.DacVoltPP = cfg->DacVoltPP; - measurementSettingsPacket.BiasVolt = cfg->BiasVolt; - measurementSettingsPacket.HstiaRtiaSel = cfg->HstiaRtiaSel; - measurementSettingsPacket.AdcPgaGain = cfg->AdcPgaGain; - measurementSettingsPacket.DftNum = cfg->DftNum; - measurementSettingsPacket.ADCAvgNum = cfg->ADCAvgNum; - activeSerial->write((uint8_t *)&measurementSettingsPacket, sizeof(measurementSettingsPacket)); - } + // Automatically save the configuration after any successful change + saveCurrentConfig(); +} - void getInitStatus(void) - { - // Count units by status - int skippedCount = 0; - int failedCount = 0; - int successCount = 0; +void getMesaurementSettings(void) +{ + // Pointer to store configuration structure + AppIMPCfg_Type *cfg; - // If Initialization function has been completely executed - if (true == isInitialized) + // Get the current impedance measurement configuration + AppIMPGetCfg(&cfg); + + measurementSettingsPacket.SinFreq = cfg->SinFreq; + measurementSettingsPacket.DacVoltPP = cfg->DacVoltPP; + measurementSettingsPacket.BiasVolt = cfg->BiasVolt; + measurementSettingsPacket.HstiaRtiaSel = cfg->HstiaRtiaSel; + measurementSettingsPacket.AdcPgaGain = cfg->AdcPgaGain; + measurementSettingsPacket.DftNum = cfg->DftNum; + measurementSettingsPacket.ADCAvgNum = cfg->ADCAvgNum; + activeSerial->write((uint8_t *)&measurementSettingsPacket, sizeof(measurementSettingsPacket)); +} + +void getInitStatus(void) +{ + // Count units by status + int skippedCount = 0; + int failedCount = 0; + int successCount = 0; + + // If Initialization function has been completely executed + if (true == isInitialized) + { + // Count number of skipped, failed and successful sensor initialization + for (int i = 0; i < 6; i++) { - // Count number of skipped, failed and successful sensor initialization - for (int i = 0; i < 6; i++) + if (unitStatus[i] == STATUS_SKIPPED) { - if (unitStatus[i] == STATUS_SKIPPED) - { - skippedCount++; - } - else if (unitStatus[i] == STATUS_FAILED) - { - failedCount++; - } - else - { // STATUS_SUCCESS - successCount++; - } + skippedCount++; } - - // If any of the sensor was skipped or failed, then - if ((skippedCount > 0) || (failedCount > 0)) + else if (unitStatus[i] == STATUS_FAILED) { - // Set init status to failed - initStatus = INIT_STATUS_FAILED; + failedCount++; } - // If all the sensors were initialized successfully, then - else if (successCount == MAX_NUM_OF_SENSORS) - { - // Set the init status to initialized. - initStatus = INIT_STATUS_INITIALIZED; - } else - { - // Still need to decide, what to do here. + { // STATUS_SUCCESS + successCount++; } } - activeSerial->write((uint8_t *)&initStatus, sizeof(initStatus)); + // If any of the sensor was skipped or failed, then + if ((skippedCount > 0) || (failedCount > 0)) + { + // Set init status to failed + initStatus = INIT_STATUS_FAILED; + } + // If all the sensors were initialized successfully, then + else if (successCount == MAX_NUM_OF_SENSORS) + { + // Set the init status to initialized. + initStatus = INIT_STATUS_INITIALIZED; + } + else + { + // Still need to decide, what to do here. + } } - void sendAllSensorData(void) + activeSerial->write((uint8_t *)&initStatus, sizeof(initStatus)); +} + +void sendAllSensorData(void) +{ + while (sendSensorData) { - while (sendSensorData) + String command = activeSerial->readStringUntil('\n'); + if (command.length() > 0) { - String command = activeSerial->readStringUntil('\n'); - if (command.length() > 0) + activeSerial->write((uint8_t)1); + break; // Exit if command received + } + else + { + if (true == getAllMesaurements()) { - activeSerial->write((uint8_t)1); - break; // Exit if command received + // Send all the sensor data to DD + activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); } - else - { - if (true == getAllMesaurements()) - { - // Send all the sensor data to DD - activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); - } - delay(250); - } + delay(250); + } } }