Skip to content
Snippets Groups Projects
Commit 85dcdabb authored by Elisabetta Pianori's avatar Elisabetta Pianori
Browse files

Merge branch 'add_fluke45' into 'devel'

Add fluke45

See merge request !299
parents 0ba1034f 5005900a
Branches
No related tags found
2 merge requests!316Merge devel into main,!299Add fluke45
Pipeline #7047264 passed
......@@ -6,6 +6,7 @@ target_sources(Meter
Keithley2000.cpp
Keithley199.cpp
Fluke8842.cpp
Fluke45.cpp
HP3478A.cpp
PM6680.cpp
DMM6500.cpp
......
#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
......@@ -9,6 +9,7 @@
// labRemote
#include "DMM6500.h"
#include "Fluke45.h"
#include "Fluke8842.h"
#include "ICom.h"
#include "IMeter.h"
......@@ -210,6 +211,19 @@ void register_meter(py::module& m) {
.value("Maximum", KeysightDAQ970A::Statistic::Maximum)
.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
py::class_<Fluke8842, IMeter, std::shared_ptr<Fluke8842>>(m, "Fluke8842")
.def(py::init<const std::string&>())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment