diff --git a/src/libPS/Keithley24XX.cpp b/src/libPS/Keithley24XX.cpp index e73668e7095553c38284b476718c8467327f43a5..69d4bc39929d7dbb3da2397fcd194eace0e669e2 100644 --- a/src/libPS/Keithley24XX.cpp +++ b/src/libPS/Keithley24XX.cpp @@ -14,6 +14,23 @@ Keithley24XX::Keithley24XX(const std::string& name) : IPowerSupply(name, {"2410","2400"}) { } +void Keithley24XX::setConfiguration(const nlohmann::json& config) +{ + for (const auto &kv : config.items()) + { + if(kv.key()=="autoVoltageRange") + { + m_autoVoltageRange=kv.value(); + } + else if(kv.key()=="autoCurrentRange") + { + m_autoCurrentRange=kv.value(); + } + } + + IPowerSupply::setConfiguration(config); +} + bool Keithley24XX::ping() { std::string result = m_com->sendreceive("*IDN?"); @@ -59,10 +76,19 @@ std::string Keithley24XX::identify() return idn; } +void Keithley24XX::autoCurrentRange(unsigned channel) +{ + if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply"); + + m_autoCurrentRange=true; +} + + void Keithley24XX::setCurrentRange(double cur, unsigned channel) { if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply"); + m_autoCurrentRange=false; m_com->send(":SOURCE:CURR:RANGE " + to_string_with_precision(cur)); } @@ -72,7 +98,9 @@ void Keithley24XX::setCurrentLevel(double cur, unsigned channel) ScopeLock lock(m_com); m_com->send(":SOURCE:FUNC CURR"); - m_com->send(":SOURCE:CURR " + to_string_with_precision(cur)); + if(m_autoCurrentRange) + m_com->send(":SOURCE:CURR:RANGE " + to_string_with_precision(cur)); + m_com->send(":SOURCE:CURR " + to_string_with_precision(cur)); } double Keithley24XX::getCurrentLevel(unsigned channel) @@ -110,10 +138,18 @@ double Keithley24XX::measureCurrent(unsigned channel) return std::stod(m_com->sendreceive(":READ?")); } +void Keithley24XX::autoVoltageRange(unsigned channel) +{ + if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply"); + + m_autoCurrentRange=true; +} + void Keithley24XX::setVoltageRange(double volt, unsigned channel) { if (channel != 1) throw std::runtime_error("Set the channel to 1 for single channel power-supply"); + m_autoCurrentRange=false; m_com->send(":SOURCE:VOLT:RANGE " + to_string_with_precision(volt)); } @@ -123,6 +159,8 @@ void Keithley24XX::setVoltageLevel(double volt, unsigned channel) ScopeLock lock(m_com); m_com->send(":SOURCE:FUNC VOLT"); + if(m_autoVoltageRange) + m_com->send(":SOURCE:VOLT:RANGE " + to_string_with_precision(volt)); m_com->send(":SOURCE:VOLT " + to_string_with_precision(volt)); } diff --git a/src/libPS/Keithley24XX.h b/src/libPS/Keithley24XX.h index 2fd69234e8c60c70f83d94e8a40f1527c7e39185..591a10dedbdfa90cd1fdf4db40a0316bedda3291 100644 --- a/src/libPS/Keithley24XX.h +++ b/src/libPS/Keithley24XX.h @@ -19,6 +19,22 @@ * * Other Keithley 24xx power supplies might be supported too, but have * not been checked. + * + * # Output Level Auto-Ranging + * The Keithley 24xx requires a range to be set on the expected output + * level (both current or voltage). Setting the auto-ranging option + * causes this class to pick the best range depending on the requested + * voltage level. + * + * There are seperate settings to control whether auto-ranging is enabled + * for current and voltage source modes. The default value is to enable + * auto-ranging for convenience. Setting the range manually via `setCurrentRange` + * or `setVoltageRange` causes the auto-ranging to be disabled. It can also be set + * at configuration via `autoCurrentRange` and `autoVoltageRange` JSON + * options. + * + * The sense ranges are always automatically set to the best choice on the + * requested compliance. */ class Keithley24XX : public IPowerSupply { @@ -26,6 +42,16 @@ public: Keithley24XX(const std::string& name); ~Keithley24XX() =default; + //! Keithley24xx specific hardware configuration + /** + * Valid keys: + * - `autoVoltageRange`: Boolean indicating whether to auto-range the output voltage level + * - `autoCurrentRange`: Boolean indicating whether to auto-range the output current level + * + * @param config JSON configuration for the given power supply only + */ + virtual void setConfiguration(const nlohmann::json& config); + /** \name Communication * @{ */ @@ -51,15 +77,24 @@ public: * @{ */ + //! @brief Enable auto-ranging for current output + /** + * @param channel channel (if any) + */ + virtual void autoCurrentRange(unsigned channel = 0); + //! @brief Set current range /** * Set the range of the Keithely current output using * the `:SOURCE:CURR:RANGE` command. * + * Calling this method disables auto-ranging. + * * @param cur maximum expected current [A] * @param channel channel (if any) */ virtual void setCurrentRange(double cur, unsigned channel = 0); + virtual void setCurrentLevel(double cur, unsigned channel = 0); virtual double getCurrentLevel(unsigned channel = 0); virtual void setCurrentProtect(double maxcur , unsigned channel = 0); @@ -72,15 +107,24 @@ public: * @{ */ + //! @brief Enable auto-ranging for voltage output + /** + * @param channel channel (if any) + */ + virtual void autoVoltageRange(unsigned channel = 0); + //! @brief Set voltage range /** * Set the range of the Keithely current output using * the `:SOURCE:VOLT:RANGE` command. * + * Calling this method disables auto-ranging. + * * @param cur maximum expected voltage [V] * @param channel channel (if any) */ virtual void setVoltageRange(double volt, unsigned channel = 0); + virtual void setVoltageLevel(double volt, unsigned channel = 0); virtual double getVoltageLevel(unsigned channel = 0); virtual void setVoltageProtect(double maxvolt , unsigned channel = 0 ); @@ -105,6 +149,16 @@ private: out << std::setprecision(n) << a_value; return out.str(); } + + /** \name Settings + * @{ + */ + + //! Auto-range the output voltage level + bool m_autoVoltageRange = true; + + //! Auto-range the output current level + bool m_autoCurrentRange = true; }; #endif diff --git a/src/libPS/python.cpp b/src/libPS/python.cpp index 34383ca2d8a63bf762fea61b5f7d826ccaf056cc..75336f981048719d691e6e47dca911873aaa9418 100755 --- a/src/libPS/python.cpp +++ b/src/libPS/python.cpp @@ -483,7 +483,9 @@ void register_ps(py::module& m){ py::class_<Keithley24XX, PyPS<Keithley24XX>, IPowerSupply, std::shared_ptr<Keithley24XX>>(m, "Keithley24XX") .def(py::init<const std::string &>()) + .def("autoCurrentRange", &Keithley24XX::autoCurrentRange) .def("setCurrentRange", &Keithley24XX::setCurrentRange) + .def("autoVoltageRange", &Keithley24XX::autoVoltageRange) .def("setVoltageRange", &Keithley24XX::setVoltageRange); py::class_<RS_HMP4040, SCPIPs, std::shared_ptr<RS_HMP4040>>(m, "RS_HMP4040")