Skip to content
Snippets Groups Projects
Commit ba18b112 authored by Ava Burton Guardino's avatar Ava Burton Guardino :sunglasses:
Browse files

Merge branch 'main' of https://gitlab.cern.ch/berkeleylab/labRemote into fdti-bugfix

parents 85f15bd6 ac0e9673
No related branches found
No related tags found
1 merge request!322updated FDTI variable to the correct ENABLE_FDTI
Pipeline #7773270 failed
Showing
with 609 additions and 15 deletions
...@@ -23,7 +23,7 @@ stages: ...@@ -23,7 +23,7 @@ stages:
stage: package stage: package
# make a docker daemon available for cibuildwheel to use # make a docker daemon available for cibuildwheel to use
tags: tags:
- docker-privileged - docker-privileged-xl
services: services:
- name: docker:dind - name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"] entrypoint: ["env", "-u", "DOCKER_HOST"]
......
...@@ -6,6 +6,7 @@ target_sources(Chiller ...@@ -6,6 +6,7 @@ target_sources(Chiller
HuberChiller.cpp HuberChiller.cpp
SPSRC211.cpp SPSRC211.cpp
PolySciLM.cpp PolySciLM.cpp
Julabo.cpp
HuberComGate.cpp HuberComGate.cpp
) )
target_link_libraries(Chiller PRIVATE Com Utils) target_link_libraries(Chiller PRIVATE Com Utils)
......
...@@ -26,6 +26,16 @@ float IChiller::getRampRate() { ...@@ -26,6 +26,16 @@ float IChiller::getRampRate() {
return 0.0; return 0.0;
} }
float IChiller::measurePressure() {
logger(logWARNING) << "measurePressure is not implemented in this chiller!";
return 0.0;
}
float IChiller::measureFlow() {
logger(logWARNING) << "measureFlow is not implemented in this chiller!";
return 0.0;
}
float IChiller::ctof(float t) { return (t * 9.0 / 5.0) + 32.0; } float IChiller::ctof(float t) { return (t * 9.0 / 5.0) + 32.0; }
float IChiller::ftoc(float t) { return (t - 32.0) * 5.0 / 9.0; } float IChiller::ftoc(float t) { return (t - 32.0) * 5.0 / 9.0; }
...@@ -53,6 +53,10 @@ class IChiller { ...@@ -53,6 +53,10 @@ class IChiller {
virtual void setRampRate(float RR); virtual void setRampRate(float RR);
//! Return the ramp rate that the chiller is set to in degree/minute //! Return the ramp rate that the chiller is set to in degree/minute
virtual float getRampRate(); virtual float getRampRate();
//! Return the current pressure of the chiller in PSI
virtual float measurePressure();
//! Return chiller flow in LPM
virtual float measureFlow();
//! Set the target temperature of the chiller //! Set the target temperature of the chiller
/** /**
* \param temp The target temperature in Celsius * \param temp The target temperature in Celsius
......
#include "Julabo.h"
#include "ChillerRegistry.h"
REGISTER_CHILLER(Julabo)
Julabo::Julabo(const std::string& name) : IChiller(name, {"Julabo"}) {}
void Julabo::init() {}
void Julabo::turnOn() { m_com->send("out_mode_05 1"); }
void Julabo::turnOff() { m_com->send("out_mode_05 0"); }
void Julabo::setTargetTemperature(float temp) {
std::string cmd = "out_sp_00";
std::stringstream ss;
ss << temp;
cmd.append(" " + ss.str());
m_com->send(cmd);
}
float Julabo::getTargetTemperature() {
std::string response = m_com->sendreceive("in_sp_00");
float temp;
if (response.substr(0, 1) == "-")
temp = -std::stof(response.substr(1));
else
temp = std::stof(response);
return temp;
}
float Julabo::measureTemperature() {
std::string response = m_com->sendreceive("in_pv_00");
float temp;
if (response.substr(0, 1) == "-")
temp = -std::stof(response.substr(1));
else
temp = std::stof(response);
return temp;
}
bool Julabo::getStatus() {
std::string response = m_com->sendreceive("status");
// Return codes:
// 01 MANUAL START --> chiller is on and can be operated manually
// 02 MANUAL STOP --> chiller is off and can be operated manually
// 03 REMOTE START --> chiller is on and can be operated remotely
// 04 REMOTE STOP --> chiller is off and can be operated remotely
if (response.find("START") != std::string::npos)
return true;
else if (response.find("STOP") != std::string::npos)
return false;
else {
logger(logDEBUG) << __PRETTY_FUNCTION__
<< " -> Unexpected response: " << response;
throw std::runtime_error("Unexpected response from chiller");
return false;
}
}
#ifndef Julabo_H
#define Julabo_H
#include <memory>
#include <stdexcept>
#include <string>
#include "IChiller.h"
#include "Logger.h"
#include "TextSerialCom.h"
//! \brief Object to interface with a Julabo series chiller
/**
* # Example configuration for a Julabo Chiller:
*
* {
* "name": "myJulaboChiller",
* "hw-type": "Chiller",
* "hw-model": "Julabo",
* "communication": {
* "protocol": "TextSerialCom",
* "termination": "\r",
* "returnTermination": "\n",
* "baudrate": "B4800",
* "port": "/dev/ttyUSB0",
* "charsize": "CS7",
* "parityBit": false,
* "flowControl": true
* }
* }
*
* The operator's manual for these chillers can be found at
* https://www.julabo.com/en-us/products/recirculating-coolers/fl-recirculating-coolers/fl1201
*/
class Julabo : public IChiller {
public:
/**
* \param com The serial communication interface connected
* to the chiller
*/
Julabo(const std::string& name);
~Julabo() = default;
//! Initialize the serial communication channel
void init();
//! Turn the chiller on
void turnOn();
//! Turn the chiller off
void turnOff();
//! Set the target temperature of the chiller
/**
* \param temp The target temperature in Celsius
*/
void setTargetTemperature(float temp);
//! Return the temperature that the chiller is set to in Celsius
float getTargetTemperature();
//! Return the current temperature of the chiller in Celsius
float measureTemperature();
//! Get the status of the chiller
/**
* \return true if chiller is in "run" mode, and false if
* it's in "standby" mode
*/
bool getStatus();
};
#endif
...@@ -7,6 +7,7 @@ namespace py = pybind11; ...@@ -7,6 +7,7 @@ namespace py = pybind11;
#include "HuberChiller.h" #include "HuberChiller.h"
#include "IChiller.h" #include "IChiller.h"
#include "Julabo.h"
#include "PolySciLM.h" #include "PolySciLM.h"
class PyIChiller : public IChiller { class PyIChiller : public IChiller {
...@@ -53,6 +54,8 @@ void register_chiller(py::module& m) { ...@@ -53,6 +54,8 @@ void register_chiller(py::module& m) {
.def("setTargetTemperature", &IChiller::setTargetTemperature) .def("setTargetTemperature", &IChiller::setTargetTemperature)
.def("getTargetTemperature", &IChiller::getTargetTemperature) .def("getTargetTemperature", &IChiller::getTargetTemperature)
.def("measureTemperature", &IChiller::measureTemperature) .def("measureTemperature", &IChiller::measureTemperature)
.def("measurePressure", &IChiller::measurePressure)
.def("measureFlow", &IChiller::measureFlow)
.def("getStatus", &IChiller::getStatus); .def("getStatus", &IChiller::getStatus);
py::class_<HuberChiller, IChiller, std::shared_ptr<HuberChiller>>( py::class_<HuberChiller, IChiller, std::shared_ptr<HuberChiller>>(
...@@ -65,6 +68,8 @@ void register_chiller(py::module& m) { ...@@ -65,6 +68,8 @@ void register_chiller(py::module& m) {
.def("setTargetTemperature", &HuberChiller::setTargetTemperature) .def("setTargetTemperature", &HuberChiller::setTargetTemperature)
.def("getTargetTemperature", &HuberChiller::getTargetTemperature) .def("getTargetTemperature", &HuberChiller::getTargetTemperature)
.def("measureTemperature", &HuberChiller::measureTemperature) .def("measureTemperature", &HuberChiller::measureTemperature)
.def("measurePressure", &HuberChiller::measurePressure)
.def("measureFlow", &HuberChiller::measureFlow)
.def("getStatus", &HuberChiller::getStatus) .def("getStatus", &HuberChiller::getStatus)
.def("getFaultStatus", &HuberChiller::getFaultStatus); .def("getFaultStatus", &HuberChiller::getFaultStatus);
...@@ -80,4 +85,16 @@ void register_chiller(py::module& m) { ...@@ -80,4 +85,16 @@ void register_chiller(py::module& m) {
.def("measureFlow", &PolySciLM::measureFlow) .def("measureFlow", &PolySciLM::measureFlow)
.def("getStatus", &PolySciLM::getStatus) .def("getStatus", &PolySciLM::getStatus)
.def("getFaultStatus", &PolySciLM::getFaultStatus); .def("getFaultStatus", &PolySciLM::getFaultStatus);
py::class_<Julabo, IChiller, std::shared_ptr<Julabo>>(m, "Julabo")
.def(py::init<const std::string&>())
.def("init", &Julabo::init)
.def("turnOn", &Julabo::turnOn)
.def("turnOff", &Julabo::turnOff)
.def("setTargetTemperature", &Julabo::setTargetTemperature)
.def("getTargetTemperature", &Julabo::getTargetTemperature)
.def("measureTemperature", &Julabo::measureTemperature)
.def("measurePressure", &Julabo::measurePressure)
.def("measureFlow", &Julabo::measureFlow)
.def("getStatus", &Julabo::getStatus);
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include <bitset>
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
...@@ -210,9 +211,31 @@ std::string SerialCom::receive() { ...@@ -210,9 +211,31 @@ std::string SerialCom::receive() {
ScopeLock lock(this); ScopeLock lock(this);
int n_read = ::read(m_dev, m_tmpbuf, MAX_READ); int n_read = ::read(m_dev, m_tmpbuf, MAX_READ);
if (n_read >= 0) if (n_read >= 0) {
return std::string(m_tmpbuf, n_read); std::string response = std::string(m_tmpbuf, n_read);
else
// Convert response if communication uses charsize different from 8
if (m_charsize != mapCHARSIZE.at("CS8")) {
std::string decoded_response;
for (size_t i = 0; i < response.length(); i++) {
unsigned char original =
static_cast<unsigned char>(response[i]);
unsigned char fixed;
if (m_charsize == mapCHARSIZE.at("CS7"))
fixed = original & 0x7F;
else if (m_charsize == mapCHARSIZE.at("CS6"))
fixed = original & 0x6F;
else if (m_charsize == mapCHARSIZE.at("CS5"))
fixed = original & 0x5F;
else
throw std::runtime_error(
"CharSize not recognized! Unable to decode response");
decoded_response.push_back(fixed);
}
response = decoded_response;
}
return response;
} else
throw std::runtime_error("Error reading from " + m_port + ": " + throw std::runtime_error("Error reading from " + m_port + ": " +
std::strerror(errno)); std::strerror(errno));
} }
......
#ifndef CHECKSUMEXCEPTION_H #ifndef CHECKSUMEXCEPTION_H
#define CHECKSUMEXCEPTION_H #define CHECKSUMEXCEPTION_H
#include <stdint.h>
#include <iostream> #include <iostream>
#include "ComException.h" #include "ComException.h"
......
#ifndef OUTOFRANGEEXCEPTION_H #ifndef OUTOFRANGEEXCEPTION_H
#define OUTOFRANGEEXCEPTION_H #define OUTOFRANGEEXCEPTION_H
#include <stdint.h>
#include <iostream> #include <iostream>
#include "ComException.h" #include "ComException.h"
......
...@@ -6,10 +6,12 @@ target_sources(Meter ...@@ -6,10 +6,12 @@ target_sources(Meter
Keithley2000.cpp Keithley2000.cpp
Keithley199.cpp Keithley199.cpp
Fluke8842.cpp Fluke8842.cpp
Fluke45.cpp
HP3478A.cpp HP3478A.cpp
PM6680.cpp PM6680.cpp
DMM6500.cpp DMM6500.cpp
KeysightDAQ970A.cpp KeysightDAQ970A.cpp
RigolDM30XX.cpp
) )
target_link_libraries(Meter PRIVATE Com Utils) target_link_libraries(Meter PRIVATE Com Utils)
target_include_directories(Meter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(Meter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
......
#include "Fluke45.h"
#include "IMeter.h"
#include "Logger.h"
#include "MeterRegistry.h"
#include "ScopeLock.h"
REGISTER_METER(Fluke45)
Fluke45::Fluke45(const std::string& name) : IMeter(name, {"Fluke45"}) {}
bool Fluke45::ping(unsigned dev) {
std::string result = "";
if (dev == 0) {
logger(logDEBUG) << "ping the multimeter.....";
result = m_com->sendreceive("*IDN?\n");
} else {
throw std::runtime_error("Other channels not implemented! ");
}
return !result.empty();
}
std::string Fluke45::identify() {
std::string idn = this->sendreceive("*IDN?");
return idn;
}
void Fluke45::reset() {
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> Initialising: ";
this->send("*RST");
}
std::string Fluke45::GetMode() { return this->sendreceive("FUNC1?"); }
void Fluke45::send(std::string cmd) {
ScopeLock lock(m_com);
m_com->send("*CLS");
logger(logDEBUG2) << __PRETTY_FUNCTION__ << " -> Sending: " << cmd;
cmd += "\r\n";
m_com->send(cmd);
std::this_thread::sleep_for(std::chrono::milliseconds(m_wait));
}
std::string Fluke45::sendreceive(std::string cmd) {
ScopeLock lock(m_com);
m_com->send("*CLS");
logger(logDEBUG2) << __PRETTY_FUNCTION__ << " -> Sending: " << cmd;
cmd += "\r\n";
m_com->send(cmd);
m_com->send("++read eoi\n\r");
std::this_thread::sleep_for(std::chrono::milliseconds(m_wait));
std::string buf = m_com->receive();
logger(logDEBUG2) << __PRETTY_FUNCTION__ << " -> Received: " << buf;
return buf;
}
std::string Fluke45::GetValue() { return this->sendreceive("VAL1?"); }
double Fluke45::measureDCV(unsigned channel) {
ScopeLock lock(m_com);
std::string CurrentMode = this->GetMode();
if (CurrentMode != "VDC") {
logger(logDEBUG2) << "Current Mode is " + CurrentMode +
", Reset the meter to VDC";
this->reset();
this->SetMode(Fluke45Mode::VOLTAGEDC);
}
if (channel > 0) // use scanner card; not implemented for Fluke 45
std::cerr << "Unimplemented channel number: " << channel << std::endl;
return std::stod(this->GetValue());
}
double Fluke45::measureDCI(unsigned channel) {
ScopeLock lock(m_com);
std::string CurrentMode = this->GetMode();
if (CurrentMode != "ADC") {
logger(logDEBUG2) << "Current Mode is " + CurrentMode +
", Reset the meter to ADC";
this->reset();
this->SetMode(Fluke45Mode::CURRENTDC);
}
if (channel > 0) // use scanner card; not implemented for Fluke 45
std::cerr << "Unimplemented channel number: " << channel << std::endl;
std::string val = this->GetValue();
return std::stod(val);
}
double Fluke45::measureRES(unsigned channel, bool use4w) {
ScopeLock lock(m_com);
std::string CurrentMode = this->GetMode();
if (CurrentMode != "OHMS") {
logger(logDEBUG2) << "Current Mode is " + CurrentMode +
", Reset the meter to OHMS";
this->reset();
this->SetMode(Fluke45Mode::OHMS);
}
if (channel > 0) // use scanner card; not implemented for Fluke 45
std::cerr << "Unimplemented channel number: " << channel << std::endl;
std::string val = this->GetValue();
return std::stod(val);
}
double Fluke45::measureCAP(unsigned channel) {
std::cerr << "Unable to measure capacitance by Fluke 45, exit. "
<< std::endl;
}
void Fluke45::SetMode(enum Fluke45Mode mode) {
switch (mode) {
case Fluke45Mode::VOLTAGEDC:
this->send("VDC; AUTO;");
break;
case Fluke45Mode::VOLTAGEAC:
this->send("VAC; AUTO;");
break;
case Fluke45Mode::CURRENTDC:
this->send("ADC; AUTO;");
break;
case Fluke45Mode::CURRENTAC:
this->send("AAC; AUTO;");
break;
case Fluke45Mode::OHMS:
this->send("OHMS; AUTO;");
break;
default:
logger(logERROR) << __PRETTY_FUNCTION__ << " : Unknown mode!";
break;
}
}
void Fluke45::checkCompatibilityList() {
// get model connected to the meter
std::string idn = this->identify();
// get list of models
std::vector<std::string> models = IMeter::getListOfModels();
if (models.empty()) {
logger(logINFO) << "No model identifier implemented for this meter. No "
"check is performed.";
return;
}
std::size_t pos = m_name.find("Fluke");
std::string brand = m_name.substr(pos, pos + 5);
std::string type = m_name.substr(pos + 5, pos + 2);
for (int i = 0; i < brand.length(); i++) {
brand[i] = toupper(brand[i]);
}
for (const std::string& model : models) {
if (idn.find(brand) != std::string::npos &&
idn.find(type) != std::string::npos)
return;
}
logger(logERROR) << "Unknown meter: " << idn;
throw std::runtime_error("Unknown meter: " + idn);
}
#ifndef Fluke45_H
#define Fluke45_H
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include "IMeter.h"
/*
Fluke45 multimeter
Author: Haoran Zhao & Emily Thompson
Date: Feb 2023
Reference 1:
Fluke 45 User Manual
https://www.testequipmentdepot.com/usedequipment/pdf/45.pdf
Reference 2:
GPIB usb controller
https://prologix.biz/gpib-usb-controller.html
*/
enum class Fluke45Mode { VOLTAGEDC, VOLTAGEAC, CURRENTDC, CURRENTAC, OHMS };
class Fluke45 : public IMeter {
public:
// constructor
Fluke45(const std::string& name);
// Reset the multimeter
void reset();
// Ping device
bool ping(unsigned dev = 0);
// Ping device
std::string identify();
// Get the current measurement mode of the multimeter
std::string GetMode();
// Get value on the display
std::string GetValue();
// Set measurement mode (VDC, VAC, ADC, AAC)
void SetMode(enum Fluke45Mode);
// Make measurements
double measureDCV(unsigned channel = 0);
double measureDCI(unsigned channel = 0);
double measureRES(unsigned channel = 0, bool use4w = false);
double measureCAP(unsigned channel = 0);
// Check if device model is supported
void checkCompatibilityList();
private:
// Send command string to reader
void send(std::string cmd);
// Send command string to meter and read the output
std::string sendreceive(std::string cmd);
// Brief wait interval, could be used between two successive measurements
std::chrono::milliseconds m_wait{900};
};
#endif
#include "RigolDM30XX.h"
#include "IMeter.h"
#include "Logger.h"
#include "MeterRegistry.h"
#include "ScopeLock.h"
#include "StringUtils.h"
REGISTER_METER(RigolDM30XX)
RigolDM30XX::RigolDM30XX(const std::string& name)
: IMeter(name, {"DM3058", "DM3058E", "DM3068"}) {}
bool RigolDM30XX::ping(unsigned /*dev*/) {
std::string result = "";
logger(logDEBUG) << "ping the multimeter.....";
result = m_com->sendreceive("*IDN?");
utils::rtrim(result);
if (result.empty()) {
throw std::runtime_error("Failed communication with the device");
} else {
logger(logDEBUG) << result;
}
return !result.empty();
}
std::string RigolDM30XX::identify() {
std::string idn = m_com->sendreceive("*IDN?");
return idn;
}
void RigolDM30XX::autowait() {
m_com->send("*OPC");
int ESRValue = 0;
while ((ESRValue & 1) == 0) {
ESRValue = std::stoi(m_com->sendreceive("*ESR?"));
std::this_thread::sleep_for(std::chrono::milliseconds(m_wait));
}
}
void RigolDM30XX::send(const std::string& cmd) {
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> Sending: " << cmd;
m_com->send("*CLS");
m_com->send(cmd);
this->autowait();
}
std::string RigolDM30XX::sendreceive(const std::string& cmd) {
m_com->send("*CLS");
std::string buf = m_com->sendreceive(cmd);
this->autowait();
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> Received: " << buf;
utils::rtrim(buf);
return buf;
}
void RigolDM30XX::reset() {
logger(logDEBUG) << __PRETTY_FUNCTION__ << " -> Initialising: ";
this->send("*RST");
}
// measure DC voltage with high precision
// take average of 10 repeatings
double RigolDM30XX::measureDCV(unsigned channel) {
ScopeLock lock(m_com);
return std::stod(this->sendreceive(":MEAS:VOLT:DC?"));
}
// measure resistance (2W or 4W)
// take average of 10 repeatings
double RigolDM30XX::measureRES(unsigned channel, bool use4w) {
std::string n_func = "RES";
if (use4w) n_func = "FRES";
ScopeLock lock(m_com);
return std::stod(this->sendreceive(":MEAS:" + n_func + "?"));
}
// measure DC current with high precision
// take average of 10 repeatings
double RigolDM30XX::measureDCI(unsigned channel) {
ScopeLock lock(m_com);
return std::stod(this->sendreceive(":MEAS:CURR:DC?"));
}
#ifndef RigolDM30XX_H
#define RigolDM30XX_H
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include "IMeter.h"
/*
RigolDM30XX single-channel multimeter
Author: Simon Koch
Date: Feb 2024
Reference 1 (User Guide, DM3068):
https://www.rigol-uk.co.uk/pdf/Rigol-DM3068-User-Guide.pdf
Reference 2 (Programmers Guide, DM3058/3058E/3068):
https://beyondmeasure.rigoltech.com/acton/attachment/1579/f-003f/0/-/-/-/-/file.pdf
Based on implementation of Keithley2000
- channel argument included only for compatibility with IMeter interface
*/
class RigolDM30XX : public IMeter {
public:
RigolDM30XX(const std::string& name);
/** ping the device
*/
virtual bool ping(unsigned dev = 0);
virtual std::string identify();
virtual void reset();
/** measure DC voltage (unit: V)
*/
virtual double measureDCV(unsigned channel = 0);
/** measure DC current (unit: A)
*/
virtual double measureDCI(unsigned channel = 0);
/* measure resistance (unit: Ohm)
*/
virtual double measureRES(unsigned channel = 0, bool use4w = false);
private:
void send(const std::string& cmd);
std::string sendreceive(const std::string& cmd);
void autowait();
std::chrono::milliseconds m_wait{10};
};
#endif
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
// labRemote // labRemote
#include "DMM6500.h" #include "DMM6500.h"
#include "Fluke45.h"
#include "Fluke8842.h" #include "Fluke8842.h"
#include "ICom.h" #include "ICom.h"
#include "IMeter.h" #include "IMeter.h"
#include "Keithley2000.h" #include "Keithley2000.h"
#include "KeysightDAQ970A.h" #include "KeysightDAQ970A.h"
#include "RigolDM30XX.h"
namespace py = pybind11; namespace py = pybind11;
...@@ -152,6 +154,20 @@ void register_meter(py::module& m) { ...@@ -152,6 +154,20 @@ void register_meter(py::module& m) {
const std::vector<unsigned>&, bool)>( const std::vector<unsigned>&, bool)>(
&Keithley2000::measureRES)); &Keithley2000::measureRES));
// RigolDM30XX
py::class_<RigolDM30XX, IMeter, std::shared_ptr<RigolDM30XX>>(m,
"RigolDM30XX")
.def(py::init<const std::string&>())
.def("ping", &RigolDM30XX::ping)
.def("identify", &RigolDM30XX::identify)
.def("reset", &RigolDM30XX::reset)
.def("measureDCV", static_cast<double (RigolDM30XX::*)(unsigned)>(
&RigolDM30XX::measureDCV))
.def("measureDCI", static_cast<double (RigolDM30XX::*)(unsigned)>(
&RigolDM30XX::measureDCI))
.def("measureRES", static_cast<double (RigolDM30XX::*)(unsigned, bool)>(
&RigolDM30XX::measureRES));
// KeysightDAQ970A // KeysightDAQ970A
py::class_<KeysightDAQ970A, IMeter, std::shared_ptr<KeysightDAQ970A>> py::class_<KeysightDAQ970A, IMeter, std::shared_ptr<KeysightDAQ970A>>
daq970a(m, "KeysightDAQ970A"); daq970a(m, "KeysightDAQ970A");
...@@ -195,6 +211,19 @@ void register_meter(py::module& m) { ...@@ -195,6 +211,19 @@ void register_meter(py::module& m) {
.value("Maximum", KeysightDAQ970A::Statistic::Maximum) .value("Maximum", KeysightDAQ970A::Statistic::Maximum)
.value("PeakToPeak", KeysightDAQ970A::Statistic::PeakToPeak); .value("PeakToPeak", KeysightDAQ970A::Statistic::PeakToPeak);
// Fluke45
py::class_<Fluke45, IMeter, std::shared_ptr<Fluke45>>(m, "Fluke45")
.def(py::init<const std::string&>())
.def("ping", &Fluke45::ping)
.def("identify", &Fluke45::identify)
.def("reset", &Fluke45::reset)
.def("measureDCV",
static_cast<double (Fluke45::*)(unsigned)>(&Fluke45::measureDCV))
.def("measureDCI",
static_cast<double (Fluke45::*)(unsigned)>(&Fluke45::measureDCI))
.def("measureRES", static_cast<double (Fluke45::*)(unsigned, bool)>(
&Fluke45::measureRES));
// Fluke8842 // Fluke8842
py::class_<Fluke8842, IMeter, std::shared_ptr<Fluke8842>>(m, "Fluke8842") py::class_<Fluke8842, IMeter, std::shared_ptr<Fluke8842>>(m, "Fluke8842")
.def(py::init<const std::string&>()) .def(py::init<const std::string&>())
......
...@@ -15,12 +15,16 @@ target_sources(PS ...@@ -15,12 +15,16 @@ target_sources(PS
DT54xxPs.cpp DT54xxPs.cpp
DT5471NPs.cpp DT5471NPs.cpp
DT5472NPs.cpp DT5472NPs.cpp
DT8033NPs.cpp
IsegPs.cpp
IsegSHR20xxPs.cpp
SorensenPs.cpp SorensenPs.cpp
RigolDP832.cpp RigolDP832.cpp
Keithley24XX.cpp Keithley24XX.cpp
Keithley22XX.cpp Keithley22XX.cpp
RS_HMP4040.cpp RS_HMP4040.cpp
RS_HMP2020.cpp RS_HMP2020.cpp
RS_NGP804.cpp
Tenma72133XX.cpp Tenma72133XX.cpp
Tenma722XXX.cpp Tenma722XXX.cpp
TTIPs.cpp TTIPs.cpp
......
...@@ -11,4 +11,4 @@ ...@@ -11,4 +11,4 @@
REGISTER_POWERSUPPLY(DT5471NPs) REGISTER_POWERSUPPLY(DT5471NPs)
DT5471NPs::DT5471NPs(const std::string& name) DT5471NPs::DT5471NPs(const std::string& name)
: DT54xxPs(name, {"DT5471"}, Polarity::Negative, 51e-6) {} : DT54xxPs(name, {"DT5471"}, IPowerSupply::Polarity::Negative, 51e-6) {}
...@@ -11,4 +11,4 @@ ...@@ -11,4 +11,4 @@
REGISTER_POWERSUPPLY(DT5472NPs) REGISTER_POWERSUPPLY(DT5472NPs)
DT5472NPs::DT5472NPs(const std::string& name) DT5472NPs::DT5472NPs(const std::string& name)
: DT54xxPs(name, {"DT5472"}, Polarity::Negative, 105e-6) {} : DT54xxPs(name, {"DT5472"}, IPowerSupply::Polarity::Negative, 105e-6) {}
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
REGISTER_POWERSUPPLY(DT54xxPs) REGISTER_POWERSUPPLY(DT54xxPs)
DT54xxPs::DT54xxPs(const std::string& name, DT54xxPs::DT54xxPs(const std::string& name,
const std::vector<std::string>& models, Polarity output, const std::vector<std::string>& models,
double imaxl) IPowerSupply::Polarity output, double imaxl)
: IPowerSupply(name, models), m_output(output), m_imaxl(imaxl) {} : IPowerSupply(name, models), m_output(output), m_imaxl(imaxl) {}
void DT54xxPs::reset() { void DT54xxPs::reset() {
...@@ -38,7 +38,7 @@ bool DT54xxPs::ping() { ...@@ -38,7 +38,7 @@ bool DT54xxPs::ping() {
void DT54xxPs::checkCompatibilityList() { void DT54xxPs::checkCompatibilityList() {
IPowerSupply::checkCompatibilityList(); IPowerSupply::checkCompatibilityList();
Polarity pol = polarity(); IPowerSupply::Polarity pol = polarity();
if (pol != m_output) throw std::runtime_error("Wrong polarity detected"); if (pol != m_output) throw std::runtime_error("Wrong polarity detected");
} }
...@@ -160,16 +160,16 @@ uint16_t DT54xxPs::status(unsigned channel) { ...@@ -160,16 +160,16 @@ uint16_t DT54xxPs::status(unsigned channel) {
return std::stoi(command("MON", "STAT")) & 0xFFFF; return std::stoi(command("MON", "STAT")) & 0xFFFF;
} }
DT54xxPs::Polarity DT54xxPs::polarity(unsigned channel) { IPowerSupply::Polarity DT54xxPs::polarity(unsigned channel) {
if (channel != 1) if (channel != 1)
throw std::runtime_error( throw std::runtime_error(
"Set the channel to 1 for single channel power-supply"); "Set the channel to 1 for single channel power-supply");
std::string polstr = command("MON", "POLARITY"); std::string polstr = command("MON", "POLARITY");
if (polstr == "-") if (polstr == "-")
return Polarity::Negative; return IPowerSupply::Polarity::Negative;
else else
return Polarity::Positive; return IPowerSupply::Polarity::Positive;
} }
void DT54xxPs::setIMonRange(IMonRange range, unsigned channel) { void DT54xxPs::setIMonRange(IMonRange range, unsigned channel) {
...@@ -239,11 +239,11 @@ std::string DT54xxPs::command(const std::string& cmd, const std::string& par, ...@@ -239,11 +239,11 @@ std::string DT54xxPs::command(const std::string& cmd, const std::string& par,
} }
double DT54xxPs::checkPolarity(double input) { double DT54xxPs::checkPolarity(double input) {
if (m_output == Polarity::Negative && input > 0) if (m_output == IPowerSupply::Polarity::Negative && input > 0)
throw std::runtime_error( throw std::runtime_error(
"Specified positive output value for a power supply that only " "Specified positive output value for a power supply that only "
"supports negative output."); "supports negative output.");
if (m_output == Polarity::Positive && input < 0) if (m_output == IPowerSupply::Polarity::Positive && input < 0)
throw std::runtime_error( throw std::runtime_error(
"Specified negative output value for a power supply that only " "Specified negative output value for a power supply that only "
"supports positive output."); "supports positive output.");
...@@ -252,5 +252,5 @@ double DT54xxPs::checkPolarity(double input) { ...@@ -252,5 +252,5 @@ double DT54xxPs::checkPolarity(double input) {
} }
double DT54xxPs::convertPolarity(double value) { double DT54xxPs::convertPolarity(double value) {
return (m_output == Polarity::Negative) ? -value : value; return (m_output == IPowerSupply::Polarity::Negative) ? -value : value;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment