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")