File Keithley2400Driver.cpp
File List > midas_fe > power > Keithley2400Driver.cpp
Go to the documentation of this file
#include "Keithley2400Driver.h"
#include <thread>
Keithley2400Driver::Keithley2400Driver() {}
Keithley2400Driver::~Keithley2400Driver() {}
Keithley2400Driver::Keithley2400Driver(std::string n, EQUIPMENT_INFO* inf) : PowerDriver(n, inf) {
std::cout << " Keithley2400 driver with " << instrumentID.size() << " channels instantiated "
<< std::endl;
}
INT Keithley2400Driver::ConnectODB() {
InitODBArray();
PowerDriver::ConnectODB();
settings["port"](5025);
settings["reply timout"](100);
settings["min reply"](2); // minimum reply , 2 chars , not 3 (not fully figured out why)
settings["ESR"](0);
settings["Max Voltage"](2000);
settings["Temp cal y-interception"](
0.6643); // based on a diode calibration measurement in zurich
settings["Temp cal slope"](-0.00188); // based on a diode calibration measurement in zurich
if (false)
return FE_ERR_ODB;
return FE_SUCCESS;
}
void Keithley2400Driver::InitODBArray() {
midas::odb settings_array = {{"Channel Names", std::array<std::string, 1>()}};
settings_array.connect("/Equipment/" + name + "/Settings");
}
bool Keithley2400Driver::AskPermissionToTurnOn(
int /*channel*/) // extra check whether it is safe to tunr on supply;
{
return true;
}
INT Keithley2400Driver::Init() {
usb = settings["USB_PORT"];
std::cout << "Call init on " << usb << std::endl;
std::string cmd = "";
std::string reply = "";
INT err;
// longer wait time for the HMP supplies //TODO What abut Keithly?
client->SetDefaultWaitTime(200);
// global reset if requested
if (settings["Global Reset On FE Start"] == true) {
cmd = "*RST\n";
if (!client->Write(cmd))
cm_msg(MERROR, "Init KEITH supply ... ", "could not global reset %s", usb.c_str());
else
cm_msg(MINFO, "power_fe", "Init global reset of %s", usb.c_str());
}
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
cmd = GenerateCommand(COMMAND_TYPE::Beep, 0);
if (!client->Write(cmd))
cm_msg(MERROR, "Init KEITH supply ... ", "could not beep %s", usb.c_str());
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
// std::vector<std::string> error_queue = ReadErrorQueue(-1,err);
// for(auto& s : error_queue)
// {
// if(s.find("No error") == std::string::npos) { cm_msg(MERROR,"power_fe"," Error from KEITH
// supply : %s",s.c_str()); }
// } //TOFIX: what's wrong???
// KEITH has 1 channel
instrumentID = {1};
int nChannels = instrumentID.size();
settings["NChannels"] = nChannels;
voltage.resize(nChannels);
demandvoltage.resize(nChannels);
demandcurrent.resize(nChannels);
current.resize(nChannels);
currentlimit.resize(nChannels);
state.resize(nChannels);
OVPlevel.resize(nChannels);
temperature.resize(nChannels);
// instrumentID = {1,2,3,4}; // The HMP4040 supply has 4 channel numbered 1,2,3, and 4.
idCode = ReadIDCode(-1, err); // channel selection not relevant for HAMEG supply to read ID
// "-1" is a trick not to select a channel before the query
std::cout << "ID code: " << idCode << std::endl;
// client->FlushQueu();
// read channels
float interception = settings["Temp cal y-interception"];
float slope = settings["Temp cal slope"];
for (int i = 0; i < nChannels; i++) {
state[i] = ReadState(i, err);
if (err != FE_SUCCESS)
return err;
}
variables["State"] = state; // push to odb
variables["Set State"] = state;
for (int i = 0; i < nChannels; i++) {
voltage[i] = ReadVoltage(i, err);
demandvoltage[i] = ReadSetVoltage(i, err);
OVPlevel[i] = ReadOVPLevel(i, err);
current[i] = ReadCurrent(i, err);
demandcurrent[i] = ReadSetCurrent(i, err);
currentlimit[i] = ReadCurrentLimit(i, err);
SourceMode.push_back(ReadSourceMode(i, err));
temperature[i] = (voltage[i] - interception) / slope;
if (err != FE_SUCCESS)
return err;
}
settings["Identification Code"] = idCode;
settings["ESR"] = ReadESR(-1, err);
settings["Read ESR"] = false;
variables["State"] = state; // push to odb
variables["Set State"] =
state; // the init function can not change the on/off state of the supply
variables["Voltage"] = voltage;
variables["Temperature"] = temperature;
variables["Demand Voltage"] = demandvoltage;
variables["Current"] = current;
variables["Demand Current"] = demandcurrent;
variables["Current Limit"] = currentlimit;
variables["OVP Level"] = OVPlevel;
variables["Demand OVP Level"] = OVPlevel;
settings["Source Mode"] = SourceMode;
// watch functions
variables["Set State"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->SetStateChanged(); });
variables["Demand Current"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->DemandCurrentChanged(); });
variables["Demand Voltage"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->DemandVoltageChanged(); });
variables["Current Limit"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->CurrentLimitChanged(); });
variables["Demand OVP Level"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->DemandOVPLevelChanged(); });
settings["Read ESR"].watch([&](midas::odb& arg [[maybe_unused]]) { this->ReadESRChanged(); });
settings["Source Mode"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->SourceModeChanged(); });
return FE_SUCCESS;
}
INT Keithley2400Driver::ReadAll() {
INT err;
INT err_accumulated;
int nChannels = instrumentID.size();
// update local book keeping
for (int i = 0; i < nChannels; i++) {
if (readonlythisindex >= 0 && i != readonlythisindex)
continue;
bool bvalue = ReadState(i, err);
err_accumulated = err;
err = 0;
if (state[i] != bvalue) // only update odb if there is a change
{
state[i] = bvalue;
variables["State"][i] = bvalue;
}
float fvalue = ReadVoltage(i, err);
err_accumulated = err_accumulated | err;
if (fabs(voltage[i] - fvalue) > fabs(relevantchange * voltage[i])) {
voltage[i] = fvalue;
variables["Voltage"][i] = fvalue;
float tvalue = (fvalue - 0.6559) / -0.00198;
temperature[i] = tvalue;
variables["Temperature"][i] = tvalue;
}
fvalue = ReadCurrent(i, err);
err_accumulated = err_accumulated | err;
if (fabs(current[i] - fvalue) > fabs(relevantchange * current[i])) {
current[i] = fvalue;
variables["Current"][i] = fvalue;
}
fvalue = ReadOVPLevel(i, err);
err_accumulated = err_accumulated | err;
if (fabs(OVPlevel[i] - fvalue) > fabs(relevantchange * OVPlevel[i])) {
OVPlevel[i] = fvalue;
variables["OVP Level"][i] = fvalue;
}
if (err_accumulated != FE_SUCCESS) {
return err_accumulated & 0xFFFE; // remove the success bit if there is any
}
}
std::vector<std::string> error_queue = ReadErrorQueue(-1, err);
for (auto& s : error_queue) {
cm_msg(MINFO, "Read KEITH supply ... ", "Error queue: %s", s.c_str());
if (s.find("No error") == std::string::npos) {
cm_msg(MERROR, "power_fe", " Error from KEITH supply : %s", s.c_str());
}
} // TOFIX: what's wrong???
return FE_SUCCESS;
}
void Keithley2400Driver::ReadESRChanged() {
INT err;
bool value = settings["Read ESR"];
if (value) {
settings["ESR"] = ReadESR(-1, err);
settings["Read ESR"] = false;
}
}
// bool Keithley2400Driver::AskPermissionToTurnOn(int channel) //extra check whether it is safe to
// tunr on supply;
// {
// return true;
// }
std::string Keithley2400Driver::GenerateCommand(COMMAND_TYPE cmdt, float val) {
if (cmdt == COMMAND_TYPE::SetCurrent) {
return ":SOUR:CURR " + std::to_string(val) + "\n";
} else if (cmdt == COMMAND_TYPE::ReadCurrent) {
return ":READ?\n";
} else if (cmdt == COMMAND_TYPE::ReadState) {
return ":OUTP?\n";
} else if (cmdt == COMMAND_TYPE::ON) {
return ":OUTP ON\n";
} else if (cmdt == COMMAND_TYPE::OFF) {
return ":OUTP OFF\n";
} else if (cmdt == COMMAND_TYPE::ReadVoltage) {
return ":READ?\n";
} else if (cmdt == COMMAND_TYPE::SetCurrentLimit) {
return ":SENS:CURR:PROT " + std::to_string(val) + "\n";
} else if (cmdt == COMMAND_TYPE::ReadCurrentLimit) {
return ":SENS:CURR:PROT?\n";
} else if (cmdt == COMMAND_TYPE::SetVoltage) {
return ":SOUR:VOLT " + std::to_string(val) + "\n";
} else if (cmdt == COMMAND_TYPE::ReadSetVoltage) {
return ":SOUR:VOLT?\n";
} else if (cmdt == COMMAND_TYPE::ReadSetCurrent) {
return ":SOUR:CURR?\n";
} else if (cmdt == COMMAND_TYPE::Beep) {
return ":SYST:BEEP 100,1\n";
} else if (cmdt == COMMAND_TYPE::CLearStatus) {
return "*CLS\n";
} else if (cmdt == COMMAND_TYPE::OPC) {
return "*OPC?\n";
} else if (cmdt == COMMAND_TYPE::ReadESR) {
return "*ESR?\n";
} else if (cmdt == COMMAND_TYPE::Reset) {
return "*RST\n";
} else if (cmdt == COMMAND_TYPE::ReadOVPLevel) {
return ":SENS:VOLT:PROT?\n";
} else if (cmdt == COMMAND_TYPE::SetOVPLevel) {
return ":SENS:VOLT:PROT " + std::to_string(val) + "\n";
} else if (cmdt == COMMAND_TYPE::SetCurrentAsRead) {
return ":FORM:ELEM CURR\n";
} else if (cmdt == COMMAND_TYPE::SetVoltageAsRead) {
return ":FORM:ELEM VOLT\n";
} else if (cmdt == COMMAND_TYPE::SetState) {
if (val == 1)
return ":OUTP ON\n";
else
return ":OUTP OFF\n";
} else if (cmdt == COMMAND_TYPE::SourceCurrent) {
return ":SOUR:FUNC CURR\n";
} else if (cmdt == COMMAND_TYPE::SourceVoltage) {
return ":SOUR:FUNC VOLT\n";
} else if (cmdt == COMMAND_TYPE::ReadSourceMode) {
return ":SOUR:FUNC?\n";
}
return "";
}
std::string Keithley2400Driver::GenerateCommand(COMMAND_TYPE cmdt, int /*ch*/, float val) {
if (cmdt == COMMAND_TYPE::SelectChannelAndSetVoltage) {
return ":SOUR:VOLT " + std::to_string(val) + "\n";
}
if (cmdt == COMMAND_TYPE::SelectChannelAndSetCurrent) {
return ":SOUR:CURR " + std::to_string(val) + "\n";
} else {
std::cout << "This function is usable only with SelectChannelAndSetVoltageorCurrent!\n";
return "";
}
}
std::string Keithley2400Driver::ReadIDCode(int index, INT& error) {
std::string id_code = PowerDriver::ReadIDCode(index, error);
int found = id_code.find("C10");
return id_code.substr(0, found - 1);
}
/*std::string Keithley2400Driver::GenerateCommand(COMMAND_TYPE cmdt, int ch, float val)
{
std::cout << "This function is not usable with Keithley2400Driver!\n";
return "";
}*/