Skip to content
Snippets Groups Projects

WIP: DT54xxPS Current Monitor Autoranging

Open Karol Krizka requested to merge dt54xxps-autorange into devel
2 files
+ 150
40
Compare changes
  • Side-by-side
  • Inline
Files
2
+ 80
25
@@ -15,6 +15,20 @@ DT54xxPs::DT54xxPs(const std::string& name) :
IPowerSupply(name, {"DT5472"})
{ }
void DT54xxPs::setConfiguration(const nlohmann::json& config)
{
IPowerSupply::setConfiguration(config);
for (const auto &kv : config.items())
{
if(kv.key()=="autorange")
{
m_autorange=kv.value();
}
}
}
void DT54xxPs::reset()
{
command("SET","OFF");
@@ -39,75 +53,91 @@ bool DT54xxPs::ping()
void DT54xxPs::turnOn(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
command("SET","ON");
while(status(channel)&Status::RampingUp)
{
double volt=measureVoltage(channel);
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> ramping up: " << volt << "V";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
waitRamp(channel);
}
void DT54xxPs::turnOff(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
command("SET","OFF");
while(status(channel)&Status::RampingDown)
{
double volt=measureVoltage(channel);
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> ramping down: " << volt << "V";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
waitRamp(channel);
}
void DT54xxPs::setCurrentLevel(double cur, unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
if(cur<1.3e-5) // empirically derived
setIMRange(true , channel);
else
setIMRange(false, channel);
command("SET", "ISET", std::to_string(cur*1e6));
}
double DT54xxPs::getCurrentLevel(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
return std::stod(command("MON","ISET"))/1e6;
}
void DT54xxPs::setCurrentProtect(double maxcur, unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
setCurrentLevel(maxcur, channel);
}
double DT54xxPs::getCurrentProtect(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
return getCurrentLevel(channel);
}
double DT54xxPs::measureCurrent(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
return std::stod(command("MON","IMON"))/1e6;
bool lowimrange = getIMRange(channel);
if(m_autorange && lowimrange) // auto-ranging needs first measurement to be done in high range
setIMRange(false, channel);
double current = std::stod(command("MON","IMON"))/1e6;
logger(logDEBUG) << __PRETTY_FUNCTION__ << "lowimrange = " << lowimrange << ", current = " << current;
// Low range seems to not work below 13uA
if(m_autorange && current<1.3e-5 && !lowimrange)
{
double oldCurrProt=getCurrentLevel(channel);
logger(logDEBUG) << __PRETTY_FUNCTION__ << "Auto-ranging...";
setIMRange(true, channel);
current = std::stod(command("MON","IMON"))/1e6;
setIMRange(false, channel);
if(oldCurrProt>1e-4) setCurrentProtect(oldCurrProt, channel);
}
return current;
}
void DT54xxPs::setVoltageLevel(double volt, unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
command("SET", "VSET", std::to_string(volt));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
waitRamp(channel);
}
double DT54xxPs::getVoltageLevel(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
return std::stod(command("MON","VSET"));
}
@@ -127,15 +157,40 @@ double DT54xxPs::getVoltageProtect(unsigned channel)
double DT54xxPs::measureVoltage(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
return std::stod(command("MON","VMON"));
}
uint16_t DT54xxPs::status(unsigned channel)
{
if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply");
if (channel != 1) throw std::runtime_error("Invalid channel: "+std::to_string(channel));
return std::stoi(command("MON","STAT"),nullptr,16)&0xFFFF;
}
void DT54xxPs::setIMRange(bool low, unsigned channel)
{
command("SET", "IMRANGE", (low)?"LOW":"HIGH");
}
bool DT54xxPs::getIMRange(unsigned channel)
{
return(command("MON", "IMRANGE")=="LOW");
}
return std::stoi(command("MON","STAT"))&0xFFFF;
void DT54xxPs::setIMAutoRange(bool enable, unsigned channel)
{
m_autorange = enable;
}
void DT54xxPs::waitRamp(unsigned channel)
{
while(status(channel)&(Status::RampingUp|Status::RampingDown))
{
double volt=measureVoltage(channel);
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> ramping: " << volt << "V";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
std::string DT54xxPs::command(const std::string& cmd, const std::string& par, const std::string& value)
Loading