Index: AD5941_interface09302025/ad5941_library_extension.cpp =================================================================== diff -u -r449f6936bd3fd84d8c4da61448702ca24015d778 -r155b2459fb174d166376c729458e8d3881e65f9b --- AD5941_interface09302025/ad5941_library_extension.cpp (.../ad5941_library_extension.cpp) (revision 449f6936bd3fd84d8c4da61448702ca24015d778) +++ AD5941_interface09302025/ad5941_library_extension.cpp (.../ad5941_library_extension.cpp) (revision 155b2459fb174d166376c729458e8d3881e65f9b) @@ -95,6 +95,9 @@ static eepromDataPacketStruct eepromDataPacket; // Stores all the eeprom data static measurementSettingsStruct measurementSettingsPacket; // Stores all the conductivity measurement settings +static Update_cfg_Status updateCfgStataus = UPDATE_CFG_STATUS_SUCCESS; +static Update_EEPROM_Status updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; + // Global variable to store the last known good configuration SavedConfig lastConfig; int propagateSettingsChanges = 0; @@ -1301,20 +1304,39 @@ if (command.startsWith("cfg,")) { handleConfigCommand(command); - Serial.println(command); - Serial.print("*"); + // Serial.println(command); + // Serial.print("*"); propagateSettingsChanges = 1; + Serial.println((int)updateCfgStataus); return; } + if (command.startsWith("mst,")) + { + updateMeasurementSettings(command); + propagateSettingsChanges = 1; + Serial.write((uint8_t *)&updateCfgStataus, sizeof(updateCfgStataus)); + Serial1.write((uint8_t *)&updateCfgStataus, sizeof(updateCfgStataus)); + return; + } + // Handle save command for doubles (format: save,value1,value2,value3,value4) if (command.startsWith("save,")) { handleSaveCommand(command); return; } + // Handle save command for doubles (format: save,value1,value2,value3,value4) + if (command.startsWith("upe,")) + { + updateEEPROMdata(command); + Serial.write((uint8_t *)&updateEepromStatus, sizeof(updateEepromStatus)); + Serial1.write((uint8_t *)&updateEepromStatus, sizeof(updateEepromStatus)); + return; + } + // Handle load command for doubles (format: load) if (command.startsWith("load")) { @@ -1645,6 +1667,7 @@ if(false == getAllMesaurements()) { Serial.write(0); + Serial1.write(0); } } break; @@ -2263,6 +2286,8 @@ { initStatus = INIT_STATUS_IN_PROGRESS; Serial.write((uint8_t *)&initStatus, sizeof(initStatus)); + Serial1.write((uint8_t *)&initStatus, sizeof(initStatus)); + // Serial.println("\nUnit Initialization"); // Serial.println("Enter 'all' to initialize all units (1-6)"); // Serial.println("Or enter specific units separated by commas (e.g., '1,3,5')"); @@ -2831,6 +2856,7 @@ } // Send all the sensor data to DD Serial.write((uint8_t *)&sensorPacket, sizeof(sensorPacket)); + Serial1.write((uint8_t *)&sensorPacket, sizeof(sensorPacket)); propagateSettingsChanges = 0; return retVal; @@ -2988,6 +3014,7 @@ singleSensorPacket.rtdRzPhase = 0.0; // RTD Rz Phase. Hard coded to 0.0 } Serial.write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); + Serial1.write((uint8_t *)&singleSensorPacket, sizeof(singleSensorPacket)); } float getRTDMeasurements(float sensor_mV) @@ -3162,6 +3189,214 @@ return rtd_resistance; } +void updateEEPROMdata(String command) +{ + updateEepromStatus = UPDATE_EEPROM_STATUS_SUCCESS; + int firstComma = command.indexOf(','); + if (firstComma < 0) + { + updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_CMD; + // Serial.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; + + 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) + { + 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) + { + // 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) + { + // Serial.println("Error: No valid values found"); + updateEepromStatus = UPDATE_EEPROM_STATUS_NO_VALID_VALUES; + return; + } + if (valueIndex > maxTotal) + { + // Serial.print("Error: Too many values, maximum is "); + // Serial.print(maxTotal); + // Serial.print(" ("); + // Serial.print(DOUBLE_COUNT); + // Serial.print(" doubles + "); + // Serial.print(maxFloats); + // Serial.println(" floats)"); + updateEepromStatus = UPDATE_EEPROM_STATUS_TOO_MANY_VALUES; + return; + } + + int doubleCount = min(valueIndex, DOUBLE_COUNT); + int floatCount = max(0, valueIndex - DOUBLE_COUNT); + + // Display the values and ask for confirmation + // Serial.print("Preparing to save "); + // Serial.print(valueIndex); + // Serial.print(" values to EEPROM ("); + // Serial.print(doubleCount); + // Serial.print(" doubles, "); + // Serial.print(floatCount); + // Serial.println(" floats):"); + + // // Display double values + // for (int i = 0; i < doubleCount; i++) + // { + // Serial.print(i); + // Serial.print(" (double): "); + // Serial.println(doubleValues[i], 10); + // } + + // // Display float values + // for (int i = 0; i < floatCount; i++) + // { + // Serial.print(i + DOUBLE_COUNT); + // Serial.print(" (float): "); + // Serial.println(floatValues[i], 6); // Floats typically have 6-7 significant digits + // } + + // Serial.println("Confirm write to EEPROM? (y/n)"); + updateEepromStatus = UPDATE_EEPROM_STATUS_WAITING_FOR_CONFIRMATION; + Serial.write((uint8_t *)&updateEepromStatus, sizeof(updateEepromStatus)); + Serial1.write((uint8_t *)&updateEepromStatus, sizeof(updateEepromStatus)); + + // Wait for user confirmation + unsigned long startTime = millis(); + const unsigned long timeout = 30000; // 30 seconds timeout + while (true) + { + // Check for timeout + if (millis() - startTime > timeout) + { + updateEepromStatus = UPDATE_EEPROM_STATUS_CONFIRMATION_TIMEOUT; + // Serial.println("Timed out waiting for confirmation. Operation aborted."); + return; + } + // Check if data is available to read + if (Serial.available() > 0) + { + char response = Serial.read(); + // Clear any remaining characters in buffer (like newline) + while (Serial.available() > 0) + { + Serial.read(); + } + // Process response + if (response == 'y' || response == 'Y') + { + // User confirmed, write to EEPROM + unsigned int baseAddress = 0; + writeMixedValues(baseAddress, doubleValues, doubleCount, floatValues, floatCount); + // Serial.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); + + // Serial.println("Verification - Values read back from EEPROM:"); + bool verificationSuccess = true; + + // Verify doubles + for (int i = 0; i < doubleCount; i++) + { + // Serial.print(i); + // Serial.print(" (double): "); + // Serial.println(readDoubles[i], 10); + if (abs(doubleValues[i] - readDoubles[i]) > 0.000000001) + { + verificationSuccess = false; + // Serial.print("Warning: Double value "); + // Serial.print(i); + // Serial.println(" does not match exactly what was written"); + updateEepromStatus = UPDATE_EEPROM_STATUS_ERR_DOUBLE_VALUES; + } + } + + // Verify floats + for (int i = 0; i < floatCount; i++) + { + // Serial.print(i + DOUBLE_COUNT); + // Serial.print(" (float): "); + // Serial.println(readFloats[i], 6); + if (abs(floatValues[i] - readFloats[i]) > 0.000001) + { + verificationSuccess = false; + // Serial.print("Warning: Float value "); + // Serial.print(i + DOUBLE_COUNT); + // Serial.println(" does not match exactly what was written"); + updateEepromStatus = UPDATE_EEPROM_STATUS_ERR_FLOAT_VALUES; + } + } + + if (verificationSuccess) + { + updateEepromStatus = UPDATE_EEPROM_STATUS_VALUES_VERIFIED; + // Serial.println("Verification successful: All values match!"); + } + // else + // { + // // Serial.println("Verification Failed, confirm device attached and powered."); + // } + return; + } + else if (response == 'n' || response == 'N') + { + + updateEepromStatus = UPDATE_EEPROM_STATUS_OPERATION_ABORTED; + // User aborted + // Serial.println("Operation aborted by user."); + return; + } + else + { + updateEepromStatus = UPDATE_EEPROM_STATUS_INVALID_RESPONSE; + // Invalid response, ask again + // Serial.println("Please enter 'y' to confirm or 'n' to abort:"); + } + } + // Small delay to prevent CPU hogging + delay(10); + } +} + void getEEPROMdata(void) { unsigned int baseAddress = 0; // Same address used in save @@ -3187,8 +3422,227 @@ } Serial.write((uint8_t *)&eepromDataPacket, sizeof(eepromDataPacket)); + Serial1.write((uint8_t *)&eepromDataPacket, sizeof(eepromDataPacket)); } +void updateMeasurementSettings(String cmd) +{ + updateCfgStataus = UPDATE_CFG_STATUS_SUCCESS; + // 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; + + // Parse command string using comma delimiter + for (uint i = 0; i < cmd.length(); i++) + { + if (cmd.charAt(i) == ',') + { + params[paramIndex] = cmd.substring(startIndex, i); + startIndex = i + 1; + paramIndex++; + + // 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 configuration structure pointer + AppIMPCfg_Type *pImpedanceCfg; + AppIMPGetCfg(&pImpedanceCfg); + + // Extract parameter name and value + String param = params[1]; + String value = params[2]; + + // Handle special commands for saving/recalling configurations + if (param == "save") + { + saveCurrentConfig(); + // Serial.println("Configuration saved"); + return; + } + else if (param == "recall") + { + recallSavedConfig(); + // Serial.println("Configuration recalled"); + return; + } + + // Process different configuration parameters + if (param == "sinfreq") + { + // Set sine wave frequency (Hz) + pImpedanceCfg->SinFreq = value.toFloat(); + // Serial.printf("Set SinFreq to: %.2f Hz\n", pImpedanceCfg->SinFreq); + } + else if (param == "dacpp") + { + // Set DAC peak-to-peak voltage (mV) + pImpedanceCfg->DacVoltPP = value.toFloat(); + // Serial.printf("Set DacVoltPP to: %.2f mV\n", pImpedanceCfg->DacVoltPP); + } + else if (param == "bias") + { + // Set DC bias voltage (mV) + pImpedanceCfg->BiasVolt = value.toFloat(); + // Serial.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(); + // Serial.print("Value:"); + // Serial.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 + updateCfgStataus = UPDATE_CFG_STATUS_NO_CHANGE_TO_TIA; + // Serial.print("no change to tia"); + + pImpedanceCfg->HstiaRtiaSel = rtia; + // Serial.printf("Set RTIA to: %s\n", value.c_str()); + currentTIA = rtia; + // Serial.print("currentTIA: "); + // Serial.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 + updateCfgStataus = UPDATE_CFG_STATUS_NO_CHANGE_TO_PGA; + + pImpedanceCfg->AdcPgaGain = pga; + // Serial.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 + updateCfgStataus = UPDATE_CFG_STATUS_NO_CHANGE_TO_DFT_NUM; + + pImpedanceCfg->DftNum = dft; + // Serial.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 + updateCfgStataus = UPDATE_CFG_STATUS_NO_CHANGE_TO_AVG_NUM; + + pImpedanceCfg->ADCAvgNum = avg; + // Serial.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; + // Serial.printf("Set sweep enable to: %d\n", pImpedanceCfg->SweepCfg.SweepEn); + } + else if (param == "sweepstart") + { + // Set sweep start frequency (Hz) + pImpedanceCfg->SweepCfg.SweepStart = value.toFloat(); + // Serial.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(); + // Serial.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(); + // Serial.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; + // Serial.printf("Set sweep log mode to: %d\n", pImpedanceCfg->SweepCfg.SweepLog); + } + else + { + // Handle unrecognized parameter + // Serial.println("Malformed command: unrecognized parameter"); + updateCfgStataus = UPDATE_CFG_STATUS_ERR_UNRECOGNIZED_PARAM; + return; + } + + // Mark that parameters have been changed and need to be applied + pImpedanceCfg->bParaChanged = bTRUE; + + // Automatically save the configuration after any successful change + saveCurrentConfig(); +} void getMesaurementSettings(void) { // Pointer to store configuration structure @@ -3205,6 +3659,7 @@ measurementSettingsPacket.DftNum = cfg->DftNum; measurementSettingsPacket.ADCAvgNum = cfg->ADCAvgNum; Serial.write((uint8_t *)&measurementSettingsPacket, sizeof(measurementSettingsPacket)); + Serial1.write((uint8_t *)&measurementSettingsPacket, sizeof(measurementSettingsPacket)); } void getInitStatus(void) @@ -3253,6 +3708,7 @@ } Serial.write((uint8_t *)&initStatus, sizeof(initStatus)); + Serial1.write((uint8_t *)&initStatus, sizeof(initStatus)); } void sendAllSensorData( void ) @@ -3329,5 +3785,4 @@ } return retVal; } - #endif /* ad5940_library_extension_C */