From c12d3601733873dca200fedd4ba24469efd6e26b Mon Sep 17 00:00:00 2001 From: Martin Vladic Date: Wed, 29 Apr 2020 16:22:03 +0200 Subject: [PATCH] voltage ramp for DCP405 R2B11 on ch on --- src/eez/index.h | 3 ++ src/eez/modules/dcm220/channel.cpp | 19 ++++++++--- src/eez/modules/dcpX05/channel.cpp | 26 ++++++++++++++- src/eez/modules/dcpX05/channel.h | 3 ++ src/eez/modules/dcpX05/dac.cpp | 52 ++++++++++++++++++++++++++--- src/eez/modules/dcpX05/dac.h | 22 ++++++++++-- src/eez/modules/psu/calibration.cpp | 4 +-- src/eez/modules/psu/channel.cpp | 20 +++++------ src/eez/modules/psu/gui/data.cpp | 10 +++--- src/eez/modules/psu/profile.cpp | 3 ++ src/eez/modules/psu/psu.cpp | 12 +++++-- src/eez/modules/psu/ramp.cpp | 2 +- src/eez/modules/psu/scpi/diag.cpp | 3 -- src/eez/modules/psu/scpi/sour.cpp | 4 +-- 14 files changed, 144 insertions(+), 39 deletions(-) diff --git a/src/eez/index.h b/src/eez/index.h index 38d5cd674..f7712aa7c 100644 --- a/src/eez/index.h +++ b/src/eez/index.h @@ -140,6 +140,8 @@ struct ChannelParams { uint32_t DAC_MAX; uint32_t ADC_MAX; + + float U_RAMP_DURATION_MIN_VALUE; }; struct ChannelInterface { @@ -219,6 +221,7 @@ static const uint16_t MODULE_TYPE_DCM224 = 224; static const uint16_t MODULE_REVISION_DCP405_R1B1 = 0x0101; static const uint16_t MODULE_REVISION_DCP405_R2B5 = 0x0205; static const uint16_t MODULE_REVISION_DCP405_R2B7 = 0x0207; +static const uint16_t MODULE_REVISION_DCP405_R2B11 = 0x020B; static const uint16_t MODULE_REVISION_DCP405_R3B1 = 0x0301; static const uint16_t MODULE_REVISION_DCP405B_R2B7 = 0x0207; diff --git a/src/eez/modules/dcm220/channel.cpp b/src/eez/modules/dcm220/channel.cpp index 7f4c0a7ec..333fdf7fa 100644 --- a/src/eez/modules/dcm220/channel.cpp +++ b/src/eez/modules/dcm220/channel.cpp @@ -57,6 +57,8 @@ static const uint16_t ADC_MAX = 65535; static const float PTOT = 155.0f; +static const float I_MON_RESOLUTION = 0.02f; + #if defined(EEZ_PLATFORM_STM32) #define REG0_CC1_MASK (1 << 1) @@ -169,7 +171,7 @@ struct Channel : ChannelInterface { float I_MAX_FOR_REMAP; float U_CAL_POINTS[2]; - float I_CAL_POINTS[2]; + float I_CAL_POINTS[6]; Channel(int slotIndex_) : ChannelInterface(slotIndex_) @@ -197,7 +199,7 @@ struct Channel : ChannelInterface { U_CAL_POINTS[0] = 2.0f; U_CAL_POINTS[1] = slot.moduleInfo->moduleType == MODULE_TYPE_DCM224 ? 22.0f : 18.0f; - params.U_CAL_NUM_POINTS = 2; + params.U_CAL_NUM_POINTS = sizeof(U_CAL_POINTS) / sizeof(float); params.U_CAL_POINTS = U_CAL_POINTS; params.U_CAL_I_SET = 1.0f; @@ -211,9 +213,13 @@ struct Channel : ChannelInterface { params.I_DEF_STEP = 0.01f; params.I_MAX_STEP = 1.0f; - I_CAL_POINTS[0] = 0.5f; - I_CAL_POINTS[1] = slot.moduleInfo->moduleType == MODULE_TYPE_DCM224 ? 4.5f : 3.5f; - params.I_CAL_NUM_POINTS = 2; + I_CAL_POINTS[0] = 0.1f; + I_CAL_POINTS[1] = 0.2f; + I_CAL_POINTS[2] = 0.3f; + I_CAL_POINTS[3] = 0.4f; + I_CAL_POINTS[4] = 0.5f; + I_CAL_POINTS[5] = slot.moduleInfo->moduleType == MODULE_TYPE_DCM224 ? 4.5f : 3.5f; + params.I_CAL_NUM_POINTS = sizeof(I_CAL_POINTS) / sizeof(float); params.I_CAL_POINTS = I_CAL_POINTS; params.I_CAL_U_SET = 20.0f; @@ -259,6 +265,8 @@ struct Channel : ChannelInterface { params.ADC_MAX = ADC_MAX; I_MAX_FOR_REMAP = slot.moduleInfo->moduleType == MODULE_TYPE_DCM224 ? 5.0f : 4.1667f; + + params.U_RAMP_DURATION_MIN_VALUE = 0.002f; } #if defined(EEZ_PLATFORM_STM32) @@ -445,6 +453,7 @@ struct Channel : ChannelInterface { const float FULL_SCALE = 2.0F; const float U_REF = 2.5F; float iMon = remap(iMonAdc, (float)ADC_MIN, 0, FULL_SCALE * ADC_MAX / U_REF, /*channel.params.I_MAX*/ I_MAX_FOR_REMAP); + iMon = roundPrec(iMon, I_MON_RESOLUTION); channel.onAdcData(ADC_DATA_TYPE_I_MON, iMon); #ifdef DEBUG diff --git a/src/eez/modules/dcpX05/channel.cpp b/src/eez/modules/dcpX05/channel.cpp index 41e8cf5b6..52429a8c2 100644 --- a/src/eez/modules/dcpX05/channel.cpp +++ b/src/eez/modules/dcpX05/channel.cpp @@ -172,6 +172,12 @@ struct Channel : ChannelInterface { params.DAC_MAX = DigitalAnalogConverter::DAC_MAX; params.ADC_MAX = AnalogDigitalConverter::ADC_MAX; + + if (slot.moduleInfo->moduleType == MODULE_TYPE_DCP405 && slot.moduleRevision <= MODULE_REVISION_DCP405_R2B11) { + params.U_RAMP_DURATION_MIN_VALUE = 0.004f; + } else { + params.U_RAMP_DURATION_MIN_VALUE = 0.002f; + } } void init(int subchannelIndex) { @@ -462,7 +468,7 @@ struct Channel : ChannelInterface { // DAC if (tasks & OUTPUT_ENABLE_TASK_DAC) { - dac.setVoltage(uSet); + dac.setVoltage(uSet, DigitalAnalogConverter::WITH_RAMP); } // Current range @@ -835,5 +841,23 @@ static Channel g_channel1(1); static Channel g_channel2(2); ChannelInterface *g_channelInterfaces[NUM_SLOTS] = { &g_channel0, &g_channel1, &g_channel2 }; +bool isDacRampActive() { + return g_channel0.dac.m_isRampActive || g_channel1.dac.m_isRampActive || g_channel2.dac.m_isRampActive; +} + +void tickDacRamp(uint32_t tickCount) { + if (g_channel0.dac.m_isRampActive) { + g_channel0.dac.tick(tickCount); + } + + if (g_channel1.dac.m_isRampActive) { + g_channel1.dac.tick(tickCount); + } + + if (g_channel2.dac.m_isRampActive) { + g_channel2.dac.tick(tickCount); + } +} + } // namespace dcpX05 } // namespace eez diff --git a/src/eez/modules/dcpX05/channel.h b/src/eez/modules/dcpX05/channel.h index 3ef5c1602..61370a164 100644 --- a/src/eez/modules/dcpX05/channel.h +++ b/src/eez/modules/dcpX05/channel.h @@ -25,5 +25,8 @@ namespace dcpX05 { extern ChannelInterface *g_channelInterfaces[NUM_SLOTS]; +bool isDacRampActive(); +void tickDacRamp(uint32_t tickCount); + } // namespace dcpX05 } // namespace eez diff --git a/src/eez/modules/dcpX05/dac.cpp b/src/eez/modules/dcpX05/dac.cpp index 833ee1593..09493bcb6 100644 --- a/src/eez/modules/dcpX05/dac.cpp +++ b/src/eez/modules/dcpX05/dac.cpp @@ -27,6 +27,7 @@ #endif #include +#include #include #include @@ -47,6 +48,8 @@ extern float g_uSet[CH_MAX]; extern float g_iSet[CH_MAX]; #endif +static const uint32_t CONF_DCP405_R2B11_RAMP_DURATION = 4000; // 4 ms + //////////////////////////////////////////////////////////////////////////////// void DigitalAnalogConverter::init() { @@ -114,13 +117,31 @@ bool DigitalAnalogConverter::test(IOExpander &ioexp, AnalogDigitalConverter &adc return g_testResult != TEST_FAILED; } +void DigitalAnalogConverter::tick(uint32_t tickCount) { +#if defined(EEZ_PLATFORM_STM32) + if (m_isRampActive) { + uint16_t value; + + uint32_t diff = tickCount - m_rampStartTime; + if (diff >= CONF_DCP405_R2B11_RAMP_DURATION) { + value = m_rampTargetValue; + m_isRampActive = false; + } else { + value = m_rampStartValue + (m_rampTargetValue - m_rampStartValue) * diff / CONF_DCP405_R2B11_RAMP_DURATION; + } + + set(DATA_BUFFER_B, value, FROM_RAMP); + } +#endif +} + //////////////////////////////////////////////////////////////////////////////// -void DigitalAnalogConverter::setVoltage(float value) { +void DigitalAnalogConverter::setVoltage(float value, RampOption rampOption) { Channel &channel = Channel::getBySlotIndex(slotIndex); #if defined(EEZ_PLATFORM_STM32) - set(DATA_BUFFER_B, remap(value, channel.params.U_MIN, (float)DAC_MIN, channel.params.U_MAX, (float)DAC_MAX)); + set(DATA_BUFFER_B, remap(value, channel.params.U_MIN, (float)DAC_MIN, channel.params.U_MAX, (float)DAC_MAX), rampOption); #endif #if defined(EEZ_PLATFORM_SIMULATOR) @@ -166,16 +187,37 @@ void DigitalAnalogConverter::setDacCurrent(uint16_t value) { #if defined(EEZ_PLATFORM_STM32) -void DigitalAnalogConverter::set(uint8_t buffer, uint16_t value) { +void DigitalAnalogConverter::set(uint8_t buffer, uint16_t value, RampOption rampOption) { Channel &channel = Channel::getBySlotIndex(slotIndex); -#ifdef DEBUG if (buffer == DATA_BUFFER_B) { + if ( + rampOption == WITH_RAMP && + g_slots[slotIndex].moduleInfo->moduleType == MODULE_TYPE_DCP405 && + g_slots[slotIndex].moduleRevision <= MODULE_REVISION_DCP405_R2B11 && + !ramp::isActive(channel) + ) { + m_isRampActive = true; + m_rampStartValue = m_rampLastValue; + m_rampTargetValue = value; + m_rampStartTime = micros(); + return; + } + + m_rampLastValue = value; + + if (rampOption != FROM_RAMP) { + m_isRampActive = false; + } + +#ifdef DEBUG debug::g_uDac[channel.channelIndex].set(value); +#endif } else { +#ifdef DEBUG debug::g_iDac[channel.channelIndex].set(value); - } #endif + } uint8_t data[3]; uint8_t result[3]; diff --git a/src/eez/modules/dcpX05/dac.h b/src/eez/modules/dcpX05/dac.h index 2188e72f4..45c1cb0c4 100644 --- a/src/eez/modules/dcpX05/dac.h +++ b/src/eez/modules/dcpX05/dac.h @@ -32,12 +32,22 @@ class DigitalAnalogConverter { uint8_t slotIndex; TestResult g_testResult; + bool m_isRampActive = false; void init(); bool test(IOExpander &ioexp, AnalogDigitalConverter &adc); - void setVoltage(float voltage); + void tick(uint32_t tickCount); + + enum RampOption { + NO_RAMP, + WITH_RAMP, + FROM_RAMP + }; + + void setVoltage(float voltage, RampOption rampOption = NO_RAMP); void setDacVoltage(uint16_t voltage); + void setCurrent(float voltage); void setDacCurrent(uint16_t current); @@ -45,11 +55,17 @@ class DigitalAnalogConverter { return m_testing; } - private: +private: bool m_testing; + // ramp + uint16_t m_rampLastValue; + uint16_t m_rampStartValue = 0; + uint16_t m_rampTargetValue; + uint32_t m_rampStartTime; + #if defined(EEZ_PLATFORM_STM32) - void set(uint8_t buffer, uint16_t value); + void set(uint8_t buffer, uint16_t value, RampOption rampOption = NO_RAMP); void set(uint8_t buffer, float value); #endif }; diff --git a/src/eez/modules/psu/calibration.cpp b/src/eez/modules/psu/calibration.cpp index 3424b03ec..c1dfaa7b9 100644 --- a/src/eez/modules/psu/calibration.cpp +++ b/src/eez/modules/psu/calibration.cpp @@ -208,8 +208,8 @@ void start(Channel &channel) { return; channel_dispatcher::outputEnable(channel, false); - channel_dispatcher::setVoltage(channel, 0); - channel_dispatcher::setCurrent(channel, 0); + channel_dispatcher::setVoltage(channel, channel.u.min); + channel_dispatcher::setCurrent(channel, channel.i.min); profile::saveToLocation(10); profile::setFreezeState(true); diff --git a/src/eez/modules/psu/channel.cpp b/src/eez/modules/psu/channel.cpp index 83da27687..3472860a6 100644 --- a/src/eez/modules/psu/channel.cpp +++ b/src/eez/modules/psu/channel.cpp @@ -1461,27 +1461,27 @@ void Channel::setPowerLimit(float limit) { } bool Channel::isVoltageWithinRange(float u) { - u = channel_dispatcher::getValuePrecision(*this, UNIT_VOLT, u); - float min =channel_dispatcher::getValuePrecision(*this, UNIT_VOLT, channel_dispatcher::getUMin(*this)); - float max =channel_dispatcher::getValuePrecision(*this, UNIT_VOLT, channel_dispatcher::getUMax(*this)); + u = channel_dispatcher::roundChannelValue(*this, UNIT_VOLT, u); + float min = channel_dispatcher::roundChannelValue(*this, UNIT_VOLT, channel_dispatcher::getUMin(*this)); + float max = channel_dispatcher::roundChannelValue(*this, UNIT_VOLT, channel_dispatcher::getUMax(*this)); return u >= min && u <= max; } bool Channel::isVoltageLimitExceeded(float u) { - return channel_dispatcher::getValuePrecision(*this, UNIT_VOLT, u) > - channel_dispatcher::getValuePrecision(*this, UNIT_VOLT, channel_dispatcher::getULimit(*this)); + return channel_dispatcher::roundChannelValue(*this, UNIT_VOLT, u) > + channel_dispatcher::roundChannelValue(*this, UNIT_VOLT, channel_dispatcher::getULimit(*this)); } bool Channel::isCurrentWithinRange(float i) { - i = channel_dispatcher::getValuePrecision(*this, UNIT_AMPER, i); - float min =channel_dispatcher::getValuePrecision(*this, UNIT_AMPER, channel_dispatcher::getIMin(*this)); - float max =channel_dispatcher::getValuePrecision(*this, UNIT_AMPER, channel_dispatcher::getIMax(*this)); + i = channel_dispatcher::roundChannelValue(*this, UNIT_AMPER, i); + float min =channel_dispatcher::roundChannelValue(*this, UNIT_AMPER, channel_dispatcher::getIMin(*this)); + float max =channel_dispatcher::roundChannelValue(*this, UNIT_AMPER, channel_dispatcher::getIMax(*this)); return i >= min && i <= max; } bool Channel::isCurrentLimitExceeded(float i) { - return channel_dispatcher::getValuePrecision(*this, UNIT_AMPER, i) > - channel_dispatcher::getValuePrecision(*this, UNIT_AMPER, channel_dispatcher::getILimit(*this)); + return channel_dispatcher::roundChannelValue(*this, UNIT_AMPER, i) > + channel_dispatcher::roundChannelValue(*this, UNIT_AMPER, channel_dispatcher::getILimit(*this)); } diff --git a/src/eez/modules/psu/gui/data.cpp b/src/eez/modules/psu/gui/data.cpp index 6438ffcfd..f8b65b5ab 100644 --- a/src/eez/modules/psu/gui/data.cpp +++ b/src/eez/modules/psu/gui/data.cpp @@ -2339,15 +2339,15 @@ void data_calibration_point_measured_value(DataOperationEnum operation, Cursor c } } else if (operation == DATA_OPERATION_GET_MIN) { if (editPage->getCalibrationValueType() == calibration::CALIBRATION_VALUE_U) { - value = MakeValue(0 - channel_dispatcher::getUMax(channel) * 1.0f, UNIT_VOLT); + value = MakeValue(-1.0f, UNIT_VOLT); } else { - value = MakeValue(0 - channel_dispatcher::getIMaxLimit(channel) * 1.0f, UNIT_AMPER); + value = MakeValue(-0.5f, UNIT_AMPER); } } else if (operation == DATA_OPERATION_GET_MAX) { if (editPage->getCalibrationValueType() == calibration::CALIBRATION_VALUE_U) { - value = MakeValue(channel_dispatcher::getUMax(channel) * 2.0f, UNIT_VOLT); + value = MakeValue(channel_dispatcher::getUMax(channel) + 1.0f, UNIT_VOLT); } else { - value = MakeValue(channel_dispatcher::getIMaxLimit(channel) * 2.0f, UNIT_AMPER); + value = MakeValue(channel_dispatcher::getIMaxLimit(channel) + 0.5f, UNIT_AMPER); } } else if (operation == DATA_OPERATION_GET_NAME) { value = editPage->getCalibrationValueType() == calibration::CALIBRATION_VALUE_U ? "Voltage" : "Current"; @@ -6045,7 +6045,7 @@ void data_channel_voltage_ramp_duration(DataOperationEnum operation, Cursor curs } else if (operation == DATA_OPERATION_GET_ALLOW_ZERO) { value = 1; } else if (operation == DATA_OPERATION_GET_MIN) { - value = MakeValue(RAMP_DURATION_MIN_VALUE, UNIT_SECOND); + value = MakeValue(Channel::get(cursor).params.U_RAMP_DURATION_MIN_VALUE, UNIT_SECOND); } else if (operation == DATA_OPERATION_GET_MAX) { value = MakeValue(RAMP_DURATION_MAX_VALUE, UNIT_SECOND); } else if (operation == DATA_OPERATION_GET_LIMIT) { diff --git a/src/eez/modules/psu/profile.cpp b/src/eez/modules/psu/profile.cpp index 3fbed9e77..860664d13 100644 --- a/src/eez/modules/psu/profile.cpp +++ b/src/eez/modules/psu/profile.cpp @@ -782,6 +782,9 @@ static bool recallState(Parameters &profile, List *lists, int recallOptions, int } channel.u.rampDuration = profile.channels[i].u_rampDuration; + if (channel.u.rampDuration > 0 && channel.u.rampDuration < channel.params.U_RAMP_DURATION_MIN_VALUE) { + channel.u.rampDuration = channel.params.U_RAMP_DURATION_MIN_VALUE; + } channel.i.rampDuration = profile.channels[i].i_rampDuration; channel.outputDelayDuration = profile.channels[i].outputDelayDuration; diff --git a/src/eez/modules/psu/psu.cpp b/src/eez/modules/psu/psu.cpp index 7e7c90320..b9cae7bee 100644 --- a/src/eez/modules/psu/psu.cpp +++ b/src/eez/modules/psu/psu.cpp @@ -61,6 +61,7 @@ #include #include +#include #include #include #include @@ -182,14 +183,16 @@ osMessageQId g_psuMessageQueueId; } // namespacee eez::psu #if defined(EEZ_PLATFORM_STM32) + extern "C" void PSU_IncTick() { g_tickCount++; using namespace eez::psu; - if (ramp::isActive()) { + if (ramp::isActive() || eez::dcpX05::isDacRampActive()) { osMessagePut(g_psuMessageQueueId, PSU_QUEUE_MESSAGE(PSU_QUEUE_MESSAGE_TYPE_TICK, 0), 0); } } + #endif namespace eez { @@ -243,8 +246,13 @@ void oneIter() { if (type == PSU_QUEUE_MESSAGE_TYPE_TICK) { #if defined(EEZ_PLATFORM_STM32) + uint32_t tickCount = micros(); + + ramp::tick(tickCount); + + dcpX05::tickDacRamp(tickCount); + if (g_tickCount % 5) { - ramp::tick(micros()); return; } #endif diff --git a/src/eez/modules/psu/ramp.cpp b/src/eez/modules/psu/ramp.cpp index 63daaa34c..97c9849bd 100644 --- a/src/eez/modules/psu/ramp.cpp +++ b/src/eez/modules/psu/ramp.cpp @@ -47,7 +47,7 @@ static void setActive(bool active, bool forceUpdate = false); void executionStart(Channel &channel) { g_execution[channel.channelIndex].state = 1; - if (channel.outputDelayDuration < OUTPUT_DELAY_DURATION_MIN_VALUE && channel.u.rampDuration < RAMP_DURATION_MIN_VALUE) { + if (channel.outputDelayDuration < OUTPUT_DELAY_DURATION_MIN_VALUE && channel.u.rampDuration < channel.params.U_RAMP_DURATION_MIN_VALUE) { channel_dispatcher::setVoltage(channel, channel.u.triggerLevel); g_execution[channel.channelIndex].voltageRampDone = true; } else { diff --git a/src/eez/modules/psu/scpi/diag.cpp b/src/eez/modules/psu/scpi/diag.cpp index 1b1fd94de..da751bfd0 100644 --- a/src/eez/modules/psu/scpi/diag.cpp +++ b/src/eez/modules/psu/scpi/diag.cpp @@ -72,10 +72,8 @@ static void printCalibrationValue(scpi_t *context, calibration::Value &value) { void printCalibrationParameters(scpi_t *context, Unit unit, uint8_t currentRange, bool calParamsExists, Channel::CalibrationValueConfiguration &calibrationValue) { const char *prefix; - void (*strcat_value)(char *str, float value); if (unit == UNIT_VOLT) { prefix = "u"; - strcat_value = strcatVoltage; } else { if (currentRange == 0) { prefix = "i_5A"; @@ -84,7 +82,6 @@ void printCalibrationParameters(scpi_t *context, Unit unit, uint8_t currentRange } else { prefix = "i"; } - strcat_value = strcatCurrent; } char buffer[128] = { 0 }; diff --git a/src/eez/modules/psu/scpi/sour.cpp b/src/eez/modules/psu/scpi/sour.cpp index c27dde20c..61340037d 100644 --- a/src/eez/modules/psu/scpi/sour.cpp +++ b/src/eez/modules/psu/scpi/sour.cpp @@ -1187,7 +1187,7 @@ scpi_result_t scpi_cmd_sourceVoltageRampDuration(scpi_t *context) { float duration; if (param.special) { if (param.content.tag == SCPI_NUM_MIN) { - duration = RAMP_DURATION_MIN_VALUE; + duration = channel->params.U_RAMP_DURATION_MIN_VALUE; } else if (param.content.tag == SCPI_NUM_MAX) { duration = RAMP_DURATION_MAX_VALUE; } else if (param.content.tag == SCPI_NUM_DEF) { @@ -1216,7 +1216,7 @@ scpi_result_t scpi_cmd_sourceVoltageRampDurationQ(scpi_t *context) { return SCPI_RES_ERR; } - return get_source_value(context, *channel, UNIT_SECOND, channel->u.rampDuration, RAMP_DURATION_MIN_VALUE, RAMP_DURATION_MAX_VALUE, RAMP_DURATION_DEF_VALUE_U); + return get_source_value(context, *channel, UNIT_SECOND, channel->u.rampDuration, channel->params.U_RAMP_DURATION_MIN_VALUE, RAMP_DURATION_MAX_VALUE, RAMP_DURATION_DEF_VALUE_U); } } // namespace scpi