Index: AD5941_interface09302025/ad5941_library_extension.cpp =================================================================== diff -u -rc8fe9095198504232955adfecb5b2b65aaec5fff -r4be37523c8348f40b96b1df7a4ef376e99c204f6 --- AD5941_interface09302025/ad5941_library_extension.cpp (.../ad5941_library_extension.cpp) (revision c8fe9095198504232955adfecb5b2b65aaec5fff) +++ AD5941_interface09302025/ad5941_library_extension.cpp (.../ad5941_library_extension.cpp) (revision 4be37523c8348f40b96b1df7a4ef376e99c204f6) @@ -90,7 +90,7 @@ // SPI Settings for Teensy 4.0 static const SPISettings SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE0); -static bool sendSensorData; +static bool sendSensorData = false; // Configuration storage structure struct SavedConfig @@ -1378,6 +1378,30 @@ return; } + // Get Single measurement for given sensor + if (command.startsWith("h,")) + { + int firstComma = command.indexOf(','); + if (firstComma > 0) + { + int unit = command.substring(firstComma + 1).toInt(); + + if ((isSensorValid (unit)) && (isSensorInitialized (unit))) + { + // Select the sensor + selectUnit(unit); + // Get single sensor data in binary format. + getSelectedSensorMeasurements(); + } + else + { + initSinglePacketToDefault(); + activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); + } + } + return; + } + // Process commands based on the first character switch (command.charAt(0)) { @@ -1699,6 +1723,7 @@ case 'g': { + sendSensorData = false; // Mesaure and transmit for all the initialized sensors if (true == getAllMesaurements()) { @@ -1712,13 +1737,6 @@ } break; - case 'h': - { - // Get single sensor data in binary format. - getSelectedSensorMeasurements(); - } - break; - case 'k': { // Get conductivity mesaurement settings in binary format. @@ -2762,123 +2780,248 @@ void detectSerial() { + unsigned long startTime = 0; // First check Serial7 explicitly + beginSerial(&Serial7, 115200); + startTime = millis(); + + while ((millis() - startTime) < 3000) + { // Wait up to 3 seconds + if (Serial7.available()) + { + activeSerial = &Serial7; + // activeSerial->println("Using Serial7 (pins 28,29)"); + return; // Done, since Serial7 is preferred + } + } delay(50); - if (Serial7.available()) + + for (int i = 0; i < 8; i++) { - activeSerial = &Serial7; - // activeSerial->println("Using Serial7 (pins 28,29)"); - return; // Done, since Serial7 is preferred - } - else - { - for (int i = 0; i < 8; i++) + beginSerial(serialPorts[i], 115200); + delay(50); // Give time for init + // For USB Serial, wait for connection + if (serialPorts[i] == &Serial) { - beginSerial(serialPorts[i], 115200); - delay(50); // Give time for init - // For USB Serial, wait for connection - if (serialPorts[i] == &Serial) + startTime = millis(); + while (!Serial && millis() - startTime < 2000) { - unsigned long start = millis(); - while (!Serial && millis() - start < 2000) - { - // Wait up to 2s for USB - } - activeSerial = serialPorts[i]; - break; + // Wait up to 2s for USB } + activeSerial = serialPorts[i]; + break; } } } -void beginSerial(Stream *s, unsigned long baud) -{ - if (s == &Serial) + void beginSerial(Stream * s, unsigned long baud) { - 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) + if (s == &Serial) { - successCount++; + 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); + } } - // If no successful units, report and return - if (successCount == 0) + // Function to measure all successfully initialized units + bool getAllMesaurements(void) { - retVal = false; // Error - // activeSerial->println("No successfully initialized units to measure!"); - return retVal; - } + int successCount = 0; + bool retVal = true; // Success - AppIMPCfg_Type *pImpedanceCfg; + // Count successful units first + for (int i = 0; i < 6; i++) + { + if (unitStatus[i] == STATUS_SUCCESS) + { + successCount++; + } + } - // 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) + // If no successful units, report and return + if (successCount == 0) { - continue; + retVal = false; // Error + // activeSerial->println("No successfully initialized units to measure!"); + return retVal; } - // Select the unit - selectUnit(unit); - if (propagateSettingsChanges) + AppIMPCfg_Type *pImpedanceCfg; + + // Loop through and measure each successful unit + for (int unit = 1; unit <= 6; unit++) { - AppIMPGetCfg(&pImpedanceCfg); - pImpedanceCfg->bParaChanged = bTRUE; + // 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 + } + } } - // 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); @@ -2906,16 +3049,65 @@ 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) { @@ -2928,908 +3120,736 @@ medianPhase = calculateMedian(phaseArray, repeatNumber); } - // Perform RTD (temperature) measurement - float rtd_res = getRTDMeasurements(rtdVoltageValue); + // 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(";"); + 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 - initPacketToDefault(unit); + initSinglePacketToDefault(); } - 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 - activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); - } - + 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)); } - propagateSettingsChanges = 0; - return retVal; -} - -void getSelectedSensorMeasurements(void) -{ - // quick patch for fixing spontaneous measurements - unsigned long currentMillis = millis(); - if (currentMillis - previousMillis >= jitterTimeout) + float getRTDMeasurements(float sensor_mV) { + AFERefCfg_Type aferef_cfg; + HSLoopCfg_Type HsLoopCfg; + DSPCfg_Type dsp_cfg; - // 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); + uint32_t adcCode_rtd, adcCode_ref; + float volt_rtd, volt_ref; + float rtd_resistance; + const float RtdRefRes = REF_RESISTOR_VALUE; - // 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) + // Wake up the AD5940 from low power mode + if (AD5940_WakeUp(10) > 10) { - // activeSerial->println(" End Settling Measurements"); + // activeSerial->println("ERROR: AD5940 wakeup timeout"); + return -1000.0f; } - } - 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); - } + // Reset LPDAC configuration before RTD measurement + LPDACCfg_Type lpdac_reset = {0}; + lpdac_reset.PowerEn = bFALSE; + AD5940_LPDACCfgS(&lpdac_reset); - // activeSerial->printf("Freq: %.2f Hz ", storedFrequency); + // Configure High-Speed Loop + HsLoopCfg.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2; + HsLoopCfg.HsDacCfg.HsDacGain = HSDACGAIN_1; + HsLoopCfg.HsDacCfg.HsDacUpdateRate = 7; - // Print the number of data points - // activeSerial->printf("DataPoints: %lu ", 1); + // 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 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); + // 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; - // Add separator and perform RTD (temperature) measurement - // activeSerial->print(";"); - float rtd_res = getRTDMeasurements(rtdVoltageValue); - // activeSerial->print("*"); - previousMillis = millis(); + // 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; - // Check for "ERROR: AD5940 wakeup timeout" - if (-1000.0f == rtd_res) - { - // In case of an error, send all 0's - initPacketToDefault(singleSensorPacket.sensorNum); - } - 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 + // Apply configuration twice (didn't seem to stick unless we did) + AD5940_HSLoopCfgS(&HsLoopCfg); + AD5940_HSLoopCfgS(&HsLoopCfg); - } - 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 - - AD5940_Delay10us(10); // Small delay between samples + // 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; } - adcCode_rtd = accRTD / NUM_RTD_SAMPLES; - // 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) + void updateEEPROMdata(String command) { - 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_SUCCESS; + int firstComma = command.indexOf(','); + if (firstComma < 0) { - 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; + updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_CMD; + // activeSerial->println("Error: Invalid save command format"); + return; } - } - return rtd_resistance; -} + String dataStr = command.substring(firstComma + 1); -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); + // 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; - // 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; + double doubleValues[DOUBLE_COUNT]; + float floatValues[maxFloats]; + int valueIndex = 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) + // Parse values + while (valueIndex < maxTotal && dataStr.length() > 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) + int commaPos = dataStr.indexOf(','); + String valueStr; + if (commaPos >= 0) { - // Store as double - doubleValues[valueIndex] = strtod(valueStr.c_str(), NULL); + valueStr = dataStr.substring(0, commaPos); + dataStr = dataStr.substring(commaPos + 1); } else { - // Store as float - floatValues[valueIndex - DOUBLE_COUNT] = strtof(valueStr.c_str(), NULL); + // Last value + valueStr = dataStr; + dataStr = ""; // Clear dataStr to end the loop } - valueIndex++; + + // 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++; + } } - } - // 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++) - { - // activeSerial->print(i); - // activeSerial->print(" (double): "); - // activeSerial->println(readDoubles[i], 10); - if (abs(doubleValues[i] - readDoubles[i]) > 0.000000001) + // Verify doubles + for (int i = 0; i < doubleCount; i++) { - DoubleVerificationSuccess = false; - break; - // activeSerial->print("Warning: Double value "); // activeSerial->print(i); - // activeSerial->println(" does not match exactly what was written"); + // 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"); + } } - } - // 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) + // Verify floats + for (int i = 0; i < floatCount; i++) { - FloatVerificationSuccess = false; - break; - // activeSerial->print("Warning: Float value "); // activeSerial->print(i + DOUBLE_COUNT); - // activeSerial->println(" does not match exactly what was written"); + // 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"); + } } + + if (DoubleVerificationSuccess && FloatVerificationSuccess) + { + updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; + // activeSerial->println("Verification successful: All values match!"); + } + else + { + updateEepromStatus = UPDATE_EEPROM_STATUS_VALUES_VERIFICATION_FAILED; + } } - if (DoubleVerificationSuccess && FloatVerificationSuccess) + void getEEPROMdata(void) { - updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; - // activeSerial->println("Verification successful: All values match!"); - } - else - { - updateEepromStatus = UPDATE_EEPROM_STATUS_VALUES_VERIFICATION_FAILED; - } -} + unsigned int baseAddress = 0; // Same address used in save -void getEEPROMdata(void) -{ - unsigned int baseAddress = 0; // Same address used in save + // Calculate maximum values we can store + int maxFloats = (128 - (DOUBLE_COUNT * 8)) / 4; - // Calculate maximum values we can store - int maxFloats = (128 - (DOUBLE_COUNT * 8)) / 4; + double doubleValues[DOUBLE_COUNT]; + float floatValues[maxFloats]; - double doubleValues[DOUBLE_COUNT]; - float floatValues[maxFloats]; + readMixedValues(baseAddress, doubleValues, DOUBLE_COUNT, floatValues, maxFloats); - readMixedValues(baseAddress, doubleValues, DOUBLE_COUNT, floatValues, maxFloats); + // Display doubles + for (int i = 0; i < DOUBLE_COUNT; i++) + { + eepromDataPacket.doubleValue[i] = doubleValues[i]; + } - // Display doubles - for (int i = 0; i < DOUBLE_COUNT; i++) - { - eepromDataPacket.doubleValue[i] = doubleValues[i]; - } + // Display floats + for (int i = 0; i < maxFloats; i++) + { + eepromDataPacket.floatValue[i] = floatValues[i]; + } - // Display floats - for (int i = 0; i < maxFloats; i++) - { - eepromDataPacket.floatValue[i] = floatValues[i]; + activeSerial->write((uint8_t *)&eepromDataPacket, sizeof(eepromDataPacket)); } - activeSerial->write((uint8_t *)&eepromDataPacket, sizeof(eepromDataPacket)); -} - -void handleMstCommand(String cmd) -{ - // Check if the first 4 characters are "mst," - if (cmd.startsWith("mst,")) + void handleMstCommand(String cmd) { - // Remove "mst," prefix - String dataPart = cmd.substring(4); - - // Split by comma - int idx = 0; - int start = 0; - int end = 0; - - while (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX && start < dataPart.length()) + // Check if the first 4 characters are "mst," + if (cmd.startsWith("mst,")) { - end = dataPart.indexOf(',', start); - if (end == -1) - end = dataPart.length(); // Last value + // 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) + while (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX && start < dataPart.length()) { - case CONDUCTIVITY_MST_PARAM_IDX_SINFREQ: - tempSettings.SinFreq = token.toFloat(); - update_param += String(cfgSettingsParam[idx]) + "," + String(tempSettings.SinFreq, 4); - break; + 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) -{ - if ((idx >= CONDUCTIVITY_MST_PARAM_IDX_SINFREQ) && (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX)) + void updateMeasurementSettings(String cmd, uint8_t idx) { - updateCfgStatus[idx] = UPDATE_CFG_STATUS_SUCCESS; - } - else - { - return; - } + if ((idx >= CONDUCTIVITY_MST_PARAM_IDX_SINFREQ) && (idx < MAX_CONDUCTIVITY_MST_PARAM_IDX)) + { + 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++) - { - if (cmd.charAt(i) == ',') + // Parse command string using comma delimiter + for (uint i = 0; i < cmd.length(); i++) { - params[paramIndex] = cmd.substring(startIndex, i); - startIndex = i + 1; - paramIndex++; + if (cmd.charAt(i) == ',') + { + 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; + // 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); + } else - updateCfgStatus[idx] = UPDATE_CFG_STATUS_NO_CHANGE_TO_AVG_NUM; + { + // Handle unrecognized parameter + // activeSerial->println("Malformed command: unrecognized parameter"); + updateCfgStatus[idx] = UPDATE_CFG_STATUS_ERR_UNRECOGNIZED_PARAM; + return; + } - pImpedanceCfg->ADCAvgNum = avg; - // activeSerial->printf("Set ADC average number to: %s\n", value.c_str()); + // Mark that parameters have been changed and need to be applied + pImpedanceCfg->bParaChanged = bTRUE; + + // Automatically save the configuration after any successful change + saveCurrentConfig(); } - else if (param == "sweep") + + void getMesaurementSettings(void) { - // 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; - } + // Pointer to store configuration structure + AppIMPCfg_Type *cfg; - // Mark that parameters have been changed and need to be applied - pImpedanceCfg->bParaChanged = bTRUE; + // Get the current impedance measurement configuration + AppIMPGetCfg(&cfg); - // Automatically save the configuration after any successful change - saveCurrentConfig(); -} + 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 getMesaurementSettings(void) -{ - // Pointer to store configuration structure - AppIMPCfg_Type *cfg; - - // 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) + void getInitStatus(void) { - // Count number of skipped, failed and successful sensor initialization - for (int i = 0; i < 6; i++) + // Count units by status + int skippedCount = 0; + int failedCount = 0; + int successCount = 0; + + // If Initialization function has been completely executed + if (true == isInitialized) { - if (unitStatus[i] == STATUS_SKIPPED) + // Count number of skipped, failed and successful sensor initialization + for (int i = 0; i < 6; i++) { - skippedCount++; + if (unitStatus[i] == STATUS_SKIPPED) + { + skippedCount++; + } + else if (unitStatus[i] == STATUS_FAILED) + { + failedCount++; + } + else + { // STATUS_SUCCESS + successCount++; + } } - else if (unitStatus[i] == STATUS_FAILED) + + // If any of the sensor was skipped or failed, then + if ((skippedCount > 0) || (failedCount > 0)) { - failedCount++; + // 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 - { // STATUS_SUCCESS - successCount++; + { + // Still need to decide, what to do here. } } - // 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. - } + activeSerial->write((uint8_t *)&initStatus, sizeof(initStatus)); } - activeSerial->write((uint8_t *)&initStatus, sizeof(initStatus)); -} - -void sendAllSensorData(void) -{ - while (sendSensorData) + void sendAllSensorData(void) { + while (sendSensorData) + { String command = activeSerial->readStringUntil('\n'); if (command.length() > 0) { @@ -3838,20 +3858,37 @@ } else { - getAllMesaurements(); + if (true == getAllMesaurements()) + { + // Send all the sensor data to DD + activeSerial->write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); + } delay(250); } } } +void initSinglePacketToDefault(void) +{ + singleSensorPacket.sensorNum = 0; // Conductivity Sensor number i.e unit 1 to 6. + singleSensorPacket.impFreq = 0.0; // Impedance Frequency + singleSensorPacket.impDataPoints = 0; // Impedance Data Points. Hard coded to 1 + singleSensorPacket.impRzMag = 0.0; // Value of medianMag + singleSensorPacket.impRzPhase = 0.0; // Value of medianPhase + singleSensorPacket.rtdFreq = 0.0; // RTD Frequency. Hard coded to 0.0 + singleSensorPacket.rtdDataPoints = 0; // Impedance Data Points. Hard coded to 1 + singleSensorPacket.rtdRzMag = 0.0; // Value of rtd_resistance + singleSensorPacket.rtdRzPhase = 0.0; // RTD Rz Phase. Hard coded to 0.0 +} + void initPacketToDefault(int unit) { if (true == isSensorValid(unit)) { // 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].sensorNum = 0; // Conductivity Sensor number i.e unit 1 to 6. sensorPacket[sensorIdx].impFreq = 0.0; // Impedance Frequency sensorPacket[sensorIdx].impDataPoints = 0; // Impedance Data Points. Hard coded to 1 sensorPacket[sensorIdx].impRzMag = 0.0; // Value of medianMag