File PowerDriver.cpp
File List > midas_fe > power > PowerDriver.cpp
Go to the documentation of this file
#include "PowerDriver.h"
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <thread>
PowerDriver::PowerDriver() {}
PowerDriver::PowerDriver(std::string n, EQUIPMENT_INFO* inf)
: info{inf}, name{n}, n_read_faults(0), read{0}, stop{0}, readstatus(FE_ERR_DISABLED) {}
PowerDriver::~PowerDriver() {
stop = 1;
if (readthread.joinable()) {
readthread.join();
}
}
INT PowerDriver::ConnectODB() {
settings.connect("/Equipment/" + name + "/Settings");
// General settings
settings["IP"]("10.10.10.10");
settings["Use Hostname"](false);
settings["Hostname"]("");
settings["NChannels"](2);
settings["Global Reset On FE Start"](false);
settings["Read ESR"](false);
settings["Connection Type"]("Tcp");
settings["Command Type"]("SCPI");
settings["USB_PORT"]("/dev/ttyUSB0");
settings["Baudrate"](19200);
settings["Character size"](8);
settings["Parity"]("None");
settings["Stop Bits"](1.0);
settings["Flow Control"]("Software");
settings["DriverName"]("");
// Variables
variables.connect("/Equipment/" + name + "/Variables");
// decimal places to check
relevantchange = 0.001; // only take action when values change more than this value
return FE_SUCCESS;
}
INT PowerDriver::Connect() {
std::string conn_type(settings["Connection Type"]);
std::cout << "Connection type: " << conn_type << std::endl;
if (conn_type == "Tcp") {
std::string hostname("");
if (settings["Use Hostname"]) {
hostname = settings["Hostname"];
// make a hostname from the eq name
if (hostname.length() < 2) {
hostname = name;
std::transform(hostname.begin(), hostname.end(), hostname.begin(),
[](unsigned char c) { return std::tolower(c); });
settings["Hostname"] = hostname;
std::cout << "Set hostname key as " << settings["Hostnafme"] << std::endl;
}
}
client =
new TCPClient(settings["IP"], settings["port"], settings["reply timout"], hostname);
} else if (conn_type == "Serial") {
std::string usbp(settings["USB_PORT"]);
std::string parit(settings["Parity"]);
std::string flw_ctrl(settings["Flow Control"]);
std::cout << "USB port = " << usbp << ", Parity = " << parit << std::endl;
client = new SerialClient(usbp, settings["Baudrate"], settings["Character size"], parit,
settings["Stop Bits"], 2000, flw_ctrl);
} else {
cm_msg(MINFO, "power_fe", "Please specify the Connection type!");
}
ss_sleep(100);
std::string ip(settings["IP"]);
min_reply_length = settings["min reply"];
if (!client->Connect()) {
cm_msg(MERROR, "Connect to power supply ... ", "could not connect to %s.", ip.c_str());
return FE_ERR_HW;
} else {
cm_msg(MINFO, "power_fe", "Init Connection to %s alive.", ip.c_str());
}
// Also start the read thread here
readthread = std::thread(&PowerDriver::ReadLoop, this);
return FE_SUCCESS;
}
void PowerDriver::ReadLoop() {
while (!stop) {
if (read) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// cm_msg(MINFO, "Power Fe ... ", "Call Read All ... ");
readstatus = ReadAll();
read = 0;
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (readonlythisindex >= 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// cm_msg(MINFO, "Power Fe ... ", "Call Read All ... ");
readstatus = ReadAll();
readonlythisindex = -1;
}
}
}
bool PowerDriver::Enabled() {
midas::odb common("/Equipment/" + name + "/Common");
return common["Enabled"];
}
bool PowerDriver::SelectChannel(int ch) {
std::string cmd(GenerateCommand(COMMAND_TYPE::SelectChannel, ch));
if (cmd.empty()) {
return true;
}
client->Write(cmd);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
if (OPC()) {
return true;
} else {
cm_msg(MERROR, "power_fe", "Not able to select channel %d.", ch);
return false;
}
}
bool PowerDriver::ClearBuffer() {
std::string cmd(GenerateCommand(COMMAND_TYPE::ClearBuffer, 0));
if (cmd.empty()) {
return true;
}
client->Write(cmd);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
// This is what I assume should be a placeholder
bool success(true);
if (success) {
return true;
} else {
cm_msg(MERROR, "power_fe", "Not able to clear the buffer %d.", 0);
return false;
}
}
bool PowerDriver::OPC() {
client->Write(GenerateCommand(COMMAND_TYPE::OPC, 0));
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply;
return client->ReadReply(&reply, min_reply_length);
}
void PowerDriver::Print() {
std::cout << "ODB settings: " << std::endl << settings.print() << std::endl;
std::cout << "ODB variables: " << std::endl << variables.print() << std::endl;
}
/******/
// **************** Read functions *************** //
/******/
float PowerDriver::Read(std::string cmd, INT& error) {
error = FE_SUCCESS;
std::string classname(getDriverName());
client->Write(cmd);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
float value = 0;
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
cm_msg(MERROR, "Power supply read ... ", "could not read after command %s.", cmd.c_str());
error = FE_ERR_DRIVER;
}
try {
if (reply.empty()) {
cm_msg(MERROR, "Power supply read...", "no reply is given as a result of command %s.",
cmd.c_str());
error = FE_ERR_DRIVER;
} else if (reply.find("smu") != std::string::npos) {
reply = reply.substr(12, 14);
value = std::stof(reply);
} else if ((reply.find_first_of("eE") != std::string::npos) ||
(classname.find("Keithley") != std::string::npos)) {
if (reply.size() > 0 && (reply[0] == '+' || reply[0] == '-')) {
reply = reply.substr(1, 14);
} else {
if (classname == "Keithley2400") {
reply = reply.substr(1, 14); // WHY??
} else {
reply = reply.substr(0, 14);
}
}
if (reply.find("E") != std::string::npos)
reply.replace(reply.find("E"), 1, "e");
std::istringstream os(reply);
os >> value;
if (os.fail())
std::cout << "Failed to convert " << reply << " into a number\n";
} else {
value = std::stof(reply);
}
} catch (const std::exception& e) {
cm_msg(MERROR, "Power supply read...", "could not convert to float %s (%s).", reply.c_str(),
e.what());
error = FE_ERR_DRIVER;
}
return value;
}
std::string PowerDriver::ReadIDCode(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
if (index >= 0) {
SelectChannel(instrumentID[index]);
}
client->Write("*IDN?\n");
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
cm_msg(MERROR, "Power supply read ... ", "could not read id supply with address %d.",
instrumentID[index]);
error = FE_ERR_DRIVER;
}
return reply;
}
std::vector<std::string> PowerDriver::ReadErrorQueue(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
if (index >= 0) {
SelectChannel(instrumentID[index]);
}
std::vector<std::string> error_queue;
std::string cmd("");
std::string classname(getDriverName());
while (1) {
cmd = GenerateCommand(COMMAND_TYPE::ReadErrorQueue, 0);
if (cmd.empty() && (classname.find("Keithley") != std::string::npos)) {
break;
}
client->Write(cmd);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
if (index >= 0) {
cm_msg(MERROR, "Power supply read ... ",
"could not read error supply with address %d.", instrumentID[index]);
} else {
cm_msg(MERROR, "Power supply read ... ", "could not read error supply.");
}
error = FE_ERR_DRIVER;
}
error_queue.push_back(reply);
if (reply.substr(0, 1) == "0" || reply.find("Queue Is Empty") != std::string::npos ||
reply.find("No error") != std::string::npos) {
break;
}
}
return error_queue;
}
int PowerDriver::ReadESR(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
if (index >= 0) {
SelectChannel(instrumentID[index]);
}
client->Write(GenerateCommand(COMMAND_TYPE::ReadESR, 0));
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
cm_msg(MERROR, "Power supply read ... ", "could not read ESR supply with address %d",
instrumentID[index]);
error = FE_ERR_DRIVER;
}
int value = 0;
std::string classname(getDriverName());
if (classname == "Keithley2400" || classname == "Keithley6487") {
std::istringstream os(reply);
os >> value;
} else {
value = std::stoi(reply);
}
return value;
}
WORD PowerDriver::ReadQCGE(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
if (index >= 0) {
SelectChannel(instrumentID[index]);
}
client->Write(GenerateCommand(COMMAND_TYPE::ReadQCGE, 0));
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
cm_msg(MERROR, "Power supply read ... ", "could not read QCGE supply with address %d",
instrumentID[index]);
error = FE_ERR_DRIVER;
}
return WORD(std::stoi(reply));
}
bool PowerDriver::ReadState(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
if (index >= 0) {
SelectChannel(instrumentID[index]);
}
client->Write(GenerateCommand(COMMAND_TYPE::ReadState, 0));
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
cm_msg(MERROR, "Power supply read ... ", "could not read off %s state supply/channel: %d.",
name.c_str(), instrumentID[index]);
error = FE_ERR_DRIVER;
}
return (reply.find("1") != std::string::npos) || (reply.find("ON") != std::string::npos);
}
std::string PowerDriver::ReadSourceMode(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
if (index >= 0) {
SelectChannel(instrumentID[index]);
}
client->Write(GenerateCommand(COMMAND_TYPE::ReadSourceMode, 0));
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
std::string reply("");
if (!client->ReadReply(&reply, min_reply_length)) {
cm_msg(MERROR, "Power supply read ... ",
"could not read off %s source mode supply/channel: %d.", name.c_str(),
instrumentID[index]);
error = FE_ERR_DRIVER;
}
// Might be wrong of me to comment this out, bring back if causing problems
// else { return reply; }
std::cout << "ReadSourceMode : reply = " << reply << std::endl;
if (reply.find("VOLT") != std::string::npos)
reply = "VOLT"; // Why???
return reply;
}
float PowerDriver::ReadVoltage(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_ERR_DRIVER;
std::string classname(getDriverName());
if (classname == "Keithley2400" || classname == "Keithley2450") {
// I guess Keithley2400 do not allow voltage reading while being off :(
if (state[index]) {
client->Write(GenerateCommand(COMMAND_TYPE::SetVoltageAsRead, 0));
error = FE_SUCCESS;
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
}
}
float value(0.f);
std::string cmd(GenerateCommand(COMMAND_TYPE::ReadVoltage, 0));
if (classname == "Keithley2450") {
// cmd = GenerateCommand(COMMAND_TYPE::ReadSetVoltage, 0);
std::string sourceMode(settings["Source Mode"]);
if (sourceMode == "VOLT") {
cmd = GenerateCommand(COMMAND_TYPE::ReadSetVoltage, 0);
Read(cmd, error);
}
}
// if (SelectChannel(instrumentID[index])) {
// if (state) {
// error = FE_SUCCESS;
// value = Read(cmd, error);
// }
// }
if (SelectChannel(instrumentID[index])) {
if (state[index]) {
error = FE_SUCCESS;
value = Read(GenerateCommand(COMMAND_TYPE::ReadVoltage, 0), error);
} else {
error = FE_SUCCESS;
}
}
return value;
}
float PowerDriver::ReadSetVoltage(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_ERR_DRIVER;
float value(0.f);
if (SelectChannel(instrumentID[index])) {
error = FE_SUCCESS;
value = Read(GenerateCommand(COMMAND_TYPE::ReadSetVoltage, 0), error);
}
return value;
}
float PowerDriver::ReadSetCurrent(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_ERR_DRIVER;
float value(0.f);
if (SelectChannel(instrumentID[index])) {
error = FE_SUCCESS;
value = Read(GenerateCommand(COMMAND_TYPE::ReadSetCurrent, 0), error);
}
return value;
}
float PowerDriver::ReadCurrent(int index, INT& error) {
bool status = 1;
std::string classname = getDriverName();
// From here on we grab the mutex until the end of the function: One transaction at a time
error = FE_SUCCESS;
const std::lock_guard<std::mutex> lock(power_mutex);
std::string cmd_set_curr = "";
if (classname == "Keithley2400" || classname == "Keithley2450") {
if (variables["State"]) {
status = 1;
} else {
status = 0;
}
if (status != 0) {
cmd_set_curr = GenerateCommand(COMMAND_TYPE::SetCurrentAsRead, 0);
}
}
if (cmd_set_curr != "") {
client->Write(cmd_set_curr);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
}
float value = 0;
if (SelectChannel(instrumentID[index]) && status != 0) {
value = Read(GenerateCommand(COMMAND_TYPE::ReadCurrent, 0), error);
}
else if (status == 0) {
value = 0;
} else
error = FE_ERR_DRIVER;
return value;
}
float PowerDriver::ReadCurrentLimit(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_ERR_DRIVER;
float value(0.f);
if (SelectChannel(instrumentID[index])) {
error = FE_SUCCESS;
value = Read(GenerateCommand(COMMAND_TYPE::ReadCurrentLimit, 0), error);
}
return value;
}
float PowerDriver::ReadOVPLevel(int index, INT& error) {
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_ERR_DRIVER;
float value(0.f);
if (SelectChannel(instrumentID[index])) {
error = FE_SUCCESS;
value = Read(GenerateCommand(COMMAND_TYPE::ReadOVPLevel, 0), error);
}
return value;
}
/******/
// **************** Set functions *************** //
/******/
bool PowerDriver::Set(std::string cmd, INT& error) {
client->Write(cmd);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
if (OPC()) {
error = FE_SUCCESS;
return true;
} else {
error = FE_ERR_DRIVER;
cm_msg(MERROR, "Power supply ... ", "command %s not succesful for %s supply", cmd.c_str(),
name.c_str());
return false;
}
}
void PowerDriver::SetCurrentLimit(int index, float value, INT& error) {
// Have to lock it here (and not in the Set() function), otherwise you might change the wrong
// channel as a consequence you can not call the Read functions or, you try to lock a second
// time
const std::lock_guard<std::mutex> lock(power_mutex);
error = FE_SUCCESS;
// Check valid range
if (value < -0.1 || value > 90.0) {
cm_msg(MERROR, "Power supply ... ", "current limit of %f not allowed", value);
variables["Current Limit"][index] = currentlimit[index]; // Disable request
error = FE_ERR_DRIVER;
return;
}
std::string classname(getDriverName());
if (SelectChannel(instrumentID[index])) {
bool success(true);
if (classname == "Keithley2400" || classname == "Keithley2450" ||
classname == "Keithley6487") {
success = Set(GenerateCommand(COMMAND_TYPE::SetCurrentLimit, value), error);
} else {
cm_msg(MINFO, "Power ... ",
"changing current limit of %s, channel %d requested, command = %d.",
name.c_str(), instrumentID[index], COMMAND_TYPE::SetCurrent);
success = Set(GenerateCommand(COMMAND_TYPE::SetCurrent, value), error);
}
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
if (success) {
readonlythisindex = index;
// voltage[index] = ReadVoltage(index,error); // These functions also have a lock_guard,
// so can not be called directly variables["Voltage"][index] = voltage[index];
} else {
error = FE_ERR_DRIVER;
}
} else {
error = FE_ERR_DRIVER;
}
}
void PowerDriver::SetVoltage(int index, float value, INT& error) {
error = FE_SUCCESS;
std::string classname(getDriverName());
if (classname == "Keithley2450") {
// cmd = GenerateCommand(COMMAND_TYPE::ReadSetCurrent, 0);
std::string sourceMode(settings["Source Mode"]);
if (sourceMode == "CURR") {
cm_msg(MERROR, "Power supply ... ",
"voltage change is not allowed for this device given the source mode.");
variables["Demand Voltage"][index] = demandvoltage[index]; // Disable request
error = FE_ERR_DISABLED;
return;
}
}
// Making sure we do not go over the limits!
if ((classname.find("Keithley") == std::string::npos) // not a Keithley
&& (value < -0.1 || value > 25.)) {
cm_msg(MERROR, "Power supply ... ", "voltage of %f not allowed.", value);
variables["Demand Voltage"][index] = demandvoltage[index]; // Disable request
error = FE_ERR_DISABLED;
return;
}
// For some reason making sure that Keithleys cant set the voltage (except the 6487 ofc)
if ((classname.find("Keithley6487") !=
std::string::npos) // a Keithley6487 is a voltage source at UZH
&& (value > 0)
// && (classname.find("6487") != std::string::npos) // the Keithley6487
) {
cm_msg(MERROR, "Power supply ... ", "voltage of %f not allowed.", value);
variables["Demand Voltage"][index] = demandvoltage[index]; // Disable request
error = FE_ERR_DISABLED;
return;
}
// Have to lock it here, otherwise you might change the wrong channel
// as a consequence you can not call the Read functions or, you try to lock a second time
const std::lock_guard<std::mutex> lock(power_mutex);
if (SelectChannel(instrumentID[index])) { // module address in the daisy chain to select
// channel, or 1/2/3/4 for the HAMEG
if (Set(GenerateCommand(COMMAND_TYPE::SelectChannelAndSetVoltage, instrumentID[index],
value),
error)) {
readonlythisindex = index;
// voltage[index] = ReadVoltage(index, error);
// variables["Voltage"][index] = voltage[index];
// current[index] = ReadCurrent(index, error);
// variables["Current"][index] = current[index];
} else {
error = FE_ERR_DRIVER;
}
} else {
error = FE_ERR_DRIVER;
}
}
void PowerDriver::SetCurrent(int index, float value, INT& error) {
error = FE_SUCCESS;
std::string classname(getDriverName());
if (classname == "Keithley2450") {
// cmd = GenerateCommand(COMMAND_TYPE::ReadSetCurrent, 0);
std::string sourceMode(settings["Source Mode"]);
if (sourceMode == "VOLT") {
cm_msg(MERROR, "Power supply ... ",
"current change is not allowed for this device given the source mode.");
variables["Demand Current"][index] = demandcurrent[index]; // Disable request
error = FE_ERR_DISABLED;
return;
} else {
if (value < 0 || value > 1e-3) {
cm_msg(MERROR, "Power supply ... ", "current of %f not allowed.", value);
variables["Demand Current"][index] = demandcurrent[index]; // Disable request
error = FE_ERR_DISABLED;
return;
}
}
}
if ((classname.find("Keithley") == std::string::npos)
// (GenerateCommand(COMMAND_TYPE::SelectChannel, 0)).empty()
// && (classname.find("Keithley") != std::string::npos) // Now the Keithley2450 is setting
// current at UZH
) {
cm_msg(MERROR, "Power supply ... ",
"current change is not allowed for this device, revisit your strategy.");
variables["Demand Current"][index] = demandcurrent[index]; // Disable request
error = FE_ERR_DISABLED;
return;
}
// Have to lock it here, otherwise you might change the wrong channel
// as a consequence you can not call the Read functions or, you try to lock a second time
const std::lock_guard<std::mutex> lock(power_mutex);
if (SelectChannel(instrumentID[index])) { // module address in the daisy chain to select
// channel, or 1/2/3/4 for the HAMEG
if (Set(GenerateCommand(COMMAND_TYPE::SelectChannelAndSetCurrent, instrumentID[index],
value),
error)) {
readonlythisindex = index;
// voltage[index] = ReadVoltage(index, error);
// variables["Voltage"][index] = voltage[index];
// current[index] = ReadCurrent(index, error);
// variables["Current"][index] = current[index];
} else {
error = FE_ERR_DRIVER;
}
} else {
error = FE_ERR_DRIVER;
}
}
void PowerDriver::SetState(int index, bool value, INT& error) {
error = FE_SUCCESS;
cm_msg(MINFO, "Power supply ... ", "request to set channel %d to %d", instrumentID[index],
value);
if (value && !AskPermissionToTurnOn(index)) {
cm_msg(MERROR, "Power supply ... ",
"changing the state of channel %d not allowed, name = %s.", instrumentID[index],
name.c_str());
variables["Set State"][index] = false; // Disable request
error = FE_ERR_DISABLED;
return;
}
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
if (SelectChannel(instrumentID[index])) {
client->Write(GenerateCommand(COMMAND_TYPE::SetState, value));
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
if (!OPC()) {
error = FE_ERR_DRIVER;
}
} else {
error = FE_ERR_DRIVER;
}
}
void PowerDriver::SetOVPLevel(int index, float value, INT& error) {
error = FE_SUCCESS;
// Making sure we do not go over the limits!
if (value < -0.1 || value > 25.) {
cm_msg(MERROR, "Power supply ... ", "voltage protection level of %f not allowed.", value);
variables["Demand OVP Level"][index] = OVPlevel[index]; // Disable request
error = FE_ERR_DISABLED;
return;
}
// From here on we grab the mutex until the end of the function: One transaction at a time
const std::lock_guard<std::mutex> lock(power_mutex);
if (SelectChannel(instrumentID[index])) { // module address in the daisy chain to select
// channel, or 1/2/3/4 for the HAMEG
if (Set(GenerateCommand(COMMAND_TYPE::SetOVPLevel, value), error)) {
readonlythisindex = index;
// voltage[index] = ReadVoltage(index,error);
// variables["Voltage"][index] = voltage[index];
// current[index] = ReadCurrent(index,error);
// variables["Current"][index] = current[index];
// OVPlevel[index] = ReadOVPLevel(index,error);
// variables["OVP Level"][index] = OVPlevel[index];
} else {
error = FE_ERR_DRIVER;
}
} else {
error = FE_ERR_DRIVER;
}
}
/******/
// **************** Watch functions *************** //
/******/
void PowerDriver::CurrentLimitChanged() {
INT err;
int nChannelsChanged(0);
for (unsigned int i(0); i < currentlimit.size(); i++) {
float value(variables["Current Limit"][i]);
if (fabs(value - currentlimit[i]) >
fabs(relevantchange *
currentlimit[i])) { // Compare to local book keeping, look for significant change
SetCurrentLimit(i, value, err);
if (err == FE_SUCCESS) {
cm_msg(MINFO, "Power supply ... ", "changing %s current limit of channel %d to %f",
name.c_str(), instrumentID[i], value);
nChannelsChanged++;
currentlimit[i] = value;
} else {
variables["Current Limit"][i] = currentlimit[i]; // Set back to local book keeping
cm_msg(MERROR, "Power supply ... ",
"changing %s current limit of channel %d to %f failed, error %d",
name.c_str(), instrumentID[i], value, err);
}
}
}
if (nChannelsChanged < 1) {
cm_msg(MINFO, "Power supply ... ", "changing current limit request of %s rejected",
name.c_str());
}
}
void PowerDriver::SetStateChanged() {
INT err;
for (unsigned int i(0); i < state.size(); i++) {
bool value(variables["Set State"][i]);
if (value != state[i]) { // Compare to local book keeping
SetState(i, value, err);
if (err == FE_SUCCESS) {
cm_msg(MINFO, "Power supply ... ", "changing %s state of channel %d to %d",
name.c_str(), instrumentID[i], value);
} else {
variables["Set State"][i] = state[i]; // Set back to local book keeping
cm_msg(MERROR, "Power supply ... ",
"changing %s state of channel %d to %d failed, error %d", name.c_str(),
instrumentID[i], value, err);
}
}
}
for (size_t i = 0; i < instrumentID.size(); i++) {
if (err == FE_SUCCESS) {
state[i] = ReadState(i, err);
}
}
variables["State"] = state; // Push to odb
}
void PowerDriver::DemandVoltageChanged() {
INT err;
int nChannelsChanged(0);
for (unsigned int i(0); i < demandvoltage.size(); i++) {
float value(variables["Demand Voltage"][i]);
if (fabs(value - demandvoltage[i]) >
fabs(relevantchange *
demandvoltage[i])) { // Compare to local book keeping, look for significant change
SetVoltage(i, value, err);
if (err == FE_SUCCESS) {
cm_msg(MINFO, "Power supply ... ", "changing %s voltage of channel %d to %f",
name.c_str(), instrumentID[i], value);
nChannelsChanged++;
demandvoltage[i] = value;
} else {
variables["Demand Voltage"][i] =
demandvoltage[i]; // Set back to local book keeping
cm_msg(MERROR, "Power supply ... ",
"changing %s voltage of channel %d to %f failed, error %d", name.c_str(),
instrumentID[i], value, err);
}
}
}
if (nChannelsChanged < 1) {
cm_msg(MINFO, "Power supply ... ", "changing voltage request of %s rejected", name.c_str());
}
}
void PowerDriver::DemandCurrentChanged() {
INT err;
int nChannelsChanged(0);
for (unsigned int i(0); i < demandcurrent.size(); i++) {
float value(variables["Demand Current"][i]);
cm_msg(MINFO, "Power supply ... ", "Trying to change %s current of channel %d to %f",
name.c_str(), instrumentID[i], value);
if (fabs(value - demandcurrent[i]) >
fabs(relevantchange *
demandcurrent[i])) { // Compare to local book keeping, look for significant change
cm_msg(MINFO, "Power supply ... ", "Setting %s current of channel %d to %f",
name.c_str(), instrumentID[i], value);
SetCurrent(i, value, err);
if (err == FE_SUCCESS) {
cm_msg(MINFO, "Power supply ... ", "changing %s current of channel %d to %f",
name.c_str(), instrumentID[i], value);
nChannelsChanged++;
demandcurrent[i] = value;
} else {
variables["Demand Current"][i] =
demandcurrent[i]; // Set back to local book keeping
cm_msg(MERROR, "Power supply ... ",
"changing %s current of channel %d to %f failed, error %d", name.c_str(),
instrumentID[i], value, err);
}
}
}
if (nChannelsChanged < 1) {
cm_msg(MINFO, "Power supply ... ", "changing current request of %s rejected", name.c_str());
}
}
void PowerDriver::DemandOVPLevelChanged() {
INT err;
int nChannelsChanged(0);
for (unsigned int i(0); i < OVPlevel.size(); i++) {
float value(variables["Demand OVP Level"][i]);
if (fabs(value - OVPlevel[i]) >
fabs(relevantchange *
OVPlevel[i])) { // Compare to local book keeping, look for significant change
SetOVPLevel(i, value, err);
if (err == FE_SUCCESS) {
cm_msg(MINFO, "Power supply ... ",
"changing %s voltage protection level of channel %d to %f", name.c_str(),
instrumentID[i], value);
nChannelsChanged++;
OVPlevel[i] = value;
variables["OVP Level"][i] = value;
} else {
variables["Demand OVP Level"][i] = OVPlevel[i]; // Set back to local book keeping
cm_msg(MERROR, "Power supply ... ",
"changing %s voltage protection level of channel %d to %f failed, error %d",
name.c_str(), instrumentID[i], value, err);
}
}
}
if (nChannelsChanged < 1) {
cm_msg(MINFO, "Power supply ... ",
"changing voltage protection level request of %s rejected", name.c_str());
}
}
void PowerDriver::SourceModeChanged() {
INT err;
for (unsigned int i = 0; i < SourceMode.size(); i++) {
std::string cmd_set_volt = "";
std::string mode = settings["Source Mode"][i];
// cm_msg(MINFO, "Power ... ", "set state = %d, current state = %d of index = %d, channel =
// %d ", value,(int)state[i],i,instrumentID[i]);
if (mode != SourceMode[i]) // compare to local book keeping
{
// only works if power supply is off
bool state = ReadState(i, err);
if (state == true) {
SetState(i, 0, err);
variables["Set State"][i] = false;
sleep(2);
}
if (mode == "VOLT") {
cmd_set_volt = GenerateCommand(COMMAND_TYPE::SourceVoltage, 0);
} else if (mode == "CURR") {
cmd_set_volt = GenerateCommand(COMMAND_TYPE::SourceCurrent, 0);
}
if (cmd_set_volt.empty()) {
cm_msg(MERROR, "Power supply ... ", "Wrong state! Need different information.");
} else {
client->Write(cmd_set_volt);
std::this_thread::sleep_for(std::chrono::milliseconds(client->GetWaitTime()));
sleep(1);
}
}
}
}
// **************** Flexiblity functions ***************** //
std::string PowerDriver::GenerateCommand(COMMAND_TYPE, float) {
std::cout << "Warning: empty base class used, no command" << std::endl;
return "";
}
std::string PowerDriver::GenerateCommand(COMMAND_TYPE, int, float) {
std::cout << "Warning: empty base class used, no command" << std::endl;
return "";
}