File Keithley2611BDriver.cpp
File List > midas_fe > power > Keithley2611BDriver.cpp
Go to the documentation of this file
#include "Keithley2611BDriver.h"
#include <thread>
Keithley2611BDriver::Keithley2611BDriver() {}
Keithley2611BDriver::~Keithley2611BDriver() {}
Keithley2611BDriver::Keithley2611BDriver(std::string n, EQUIPMENT_INFO* inf) : PowerDriver(n, inf) {
std::cout << " Keithley2611B driver with " << instrumentID.size() << " channels instantiated "
<< std::endl;
}
INT Keithley2611BDriver::ConnectODB() {
InitODBArray();
PowerDriver::ConnectODB();
settings["port"](5025);
settings["reply timout"](300);
settings["min reply"](2); // minimum reply , 2 chars , not 3 (not fully figured out why)
settings["ESR"](0);
settings["Max Voltage"](2);
if (false)
return FE_ERR_ODB;
return FE_SUCCESS;
}
void Keithley2611BDriver::InitODBArray() {
midas::odb settings_array = {{"Channel Names", std::array<std::string, 4>()}};
settings_array.connect("/Equipment/" + name + "/Settings");
}
INT Keithley2611BDriver::Init() {
ip = settings["IP"];
std::cout << "Call init on " << ip << std::endl;
std::string cmd = "";
std::string reply = "";
INT err;
// longer wait time for the HMP supplies //TODO What abut Keithly?
client->SetDefaultWaitTime(50);
// 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", ip.c_str());
else
cm_msg(MINFO, "power_fe", "Init global reset of %s", ip.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", ip.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("Queue Is Empty") == std::string::npos) {
cm_msg(MERROR, "power_fe", " Error from KEITH supply : %s", s.c_str());
}
}
// KEITH has 1 channel
instrumentID = {1};
int nChannels = instrumentID.size();
settings["NChannels"] = nChannels;
voltage.resize(nChannels);
demandvoltage.resize(nChannels);
current.resize(nChannels);
currentlimit.resize(nChannels);
state.resize(nChannels);
OVPlevel.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
for (int i = 0; i < nChannels; i++) {
state[i] = ReadState(i, err);
voltage[i] = ReadVoltage(i, err);
demandvoltage[i] = ReadSetVoltage(i, err); // T
current[i] = ReadCurrent(i, err);
currentlimit[i] = ReadCurrentLimit(i, err);
OVPlevel[i] = ReadOVPLevel(i, err);
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["Demand Voltage"] = demandvoltage;
variables["Current"] = current;
variables["Current Limit"] = currentlimit;
variables["OVP Level"] = OVPlevel;
variables["Demand OVP Level"] = OVPlevel;
// watch functions
variables["Current Limit"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->CurrentLimitChanged(); });
variables["Set State"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->SetStateChanged(); });
variables["Demand Voltage"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->DemandVoltageChanged(); });
variables["Demand OVP Level"].watch(
[&](midas::odb& arg [[maybe_unused]]) { this->DemandOVPLevelChanged(); });
settings["Read ESR"].watch([&](midas::odb& arg [[maybe_unused]]) { this->ReadESRChanged(); });
return FE_SUCCESS;
}
INT Keithley2611BDriver::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;
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;
}
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) {
if (s.find("Queue Is Empty") == std::string::npos) {
cm_msg(MERROR, "power_fe", " Error from KEITH supply : %s", s.c_str());
}
}
return FE_SUCCESS;
}
void Keithley2611BDriver::ReadESRChanged() {
INT err;
bool value = settings["Read ESR"];
if (value) {
settings["ESR"] = ReadESR(-1, err);
settings["Read ESR"] = false;
}
}
bool Keithley2611BDriver::AskPermissionToTurnOn(
int) // extra check whether it is safe to tunr on supply;
{
return true;
}
std::string Keithley2611BDriver::GenerateCommand(COMMAND_TYPE cmdt, float val) {
if (cmdt == COMMAND_TYPE::SetCurrent) {
return "smua.source.limiti=" + std::to_string(val) + "\n";
} else if (cmdt == COMMAND_TYPE::ReadCurrent) {
return "print(smua.measure.i())\n";
} else if (cmdt == COMMAND_TYPE::ReadState) {
return "print(smua.source.output)\n";
} else if (cmdt == COMMAND_TYPE::ReadVoltage) {
return "print(smua.measure.v())\n";
} else if (cmdt == COMMAND_TYPE::ReadSetVoltage) {
return "print(smua.source.levelv)\n";
} else if (cmdt == COMMAND_TYPE::ReadCurrentLimit) {
return "print(smua.source.limiti)\n";
} else if (cmdt == COMMAND_TYPE::SetVoltage) {
return "smua.source.levelv=" + std::to_string(val) + "\n";
} else if (cmdt == COMMAND_TYPE::Beep) {
return "beeper.beep(0.5, 4400)\n"; // TODO try out
} 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::SetState) {
int ch = (int)val;
return "smua.source.output=" + std::to_string(ch) + "\n";
} else if (cmdt == COMMAND_TYPE::ReadErrorQueue) {
return "print(errorqueue.next())\n";
} else if (cmdt == COMMAND_TYPE::ReadOVPLevel) {
return "print(smua.source.limitv)\n";
} else if (cmdt == COMMAND_TYPE::SetOVPLevel) {
return "smua.source.limitv=" + std::to_string(val) + "\n";
}
return "";
}
std::string Keithley2611BDriver::GenerateCommand(COMMAND_TYPE cmdt, int, float val) {
if (cmdt == COMMAND_TYPE::SelectChannelAndSetVoltage) {
return "smua.source.levelv=" + std::to_string(val) + "\n";
} else {
std::cout << "This function is usable only with SelectChannelAndSetVoltage!\n";
return "";
}
}