diff --git a/configs/lr_iviscan.json b/configs/lr_iviscan.json
index 637179bbe96583d4049ab027fa9678fa6221e143..6c1a3759dc2b33e33fd6324820bb0e42f5c568cb 100644
--- a/configs/lr_iviscan.json
+++ b/configs/lr_iviscan.json
@@ -5,10 +5,10 @@
         {
             "name": "HV",
             "initial_voltage": 0,
-            "final_voltage": -150,
+            "final_voltage": -200,
             "step_size": -5,
-            "measurements_per_step": 3,
-            "sleeping_time_per_step_s": 10,
+            "measurements_per_step": 10,
+            "sleeping_time_per_step_s": 2,
             "current_protection": 0.0001
         },
         "passive_channels":
@@ -34,4 +34,4 @@
         [
         ]
     }
-}
\ No newline at end of file
+}
diff --git a/libDCS/iviscan.py b/libDCS/iviscan.py
index e68434045f6454e84829066ed03ae0e7929a02bd..6a5ff4eff69d50ea0a13eb5b3a7fc10f28292e0f 100644
--- a/libDCS/iviscan.py
+++ b/libDCS/iviscan.py
@@ -6,6 +6,7 @@ import numpy as np
 import time
 import getpass
 from influxdb import InfluxDBClient, exceptions
+import logging, coloredlogs, verboselogs
 
 # LR stuff
 LABREMOTE = 1
@@ -18,31 +19,14 @@ except:
         LABREMOTE = 0
 
 
-
 def sigint_handler(sig, frame):
-    print('[ info ][ ivi ] Received SIGINT. Exiting!')
+    logger.info('Received SIGINT. Exiting!')
     sys.exit(0)
 
 
 signal.signal(signal.SIGINT, sigint_handler)
 
 
-def meas_voltage(hw, ps, args):
-    return ps.measureVoltage()
-
-def power_on(hw, ps, args):
-    if args.voltage_level and args.current_protect:
-        ps.setVoltageLevel(args.voltage_level)
-        ps.setCurrentProtect(args.current_protect)
-    ps.turnOn()
-    return 0
-
-
-def power_off(hw, ps, args):
-    ps.turnOff()
-    return 0
-
-
 def powerPassiveChannels(config, key, what):
     
     if what == "turnOn":
@@ -51,8 +35,7 @@ def powerPassiveChannels(config, key, what):
 
                 ps = hw.getPowerSupplyChannel(elem["name"])
 
-                print()
-                print("setting I to %2g A and V to %2g V on channel %s" % (elem["current"], elem["voltage"], elem["name"]))
+                logger.info("setting I to %2g A and V to %2g V on channel %s" % (elem["current"], elem["voltage"], elem["name"]))
                 ps.setVoltageLevel(elem["voltage"])
                 ps.setCurrentLevel(elem["current"])
 
@@ -65,6 +48,70 @@ def powerPassiveChannels(config, key, what):
                 ps.turnOn()
 
 
+def ramp(varName, pschannel, target, step = None, tsleep = None):
+
+    if varName == "voltage":
+
+        xVarName = "voltage" ; xUnit = "V"
+        yVarName = "current" ; yUnit = "A"
+        measXvar = pschannel.measureVoltage
+        setXvar = pschannel.setVoltageLevel
+        measYvar = pschannel.measureCurrent
+        tolerance = 1 # V
+        if step   is None: step = 5 # V
+        if tsleep is None: tsleep = 1 # s
+
+    elif varName == "current":
+        
+        xVarName = "current" ; xUnit = "A"
+        yVarName = "voltage" ; yUnit = "V"
+        measXvar = pschannel.measureCurrent
+        setXvar = pschannel.setCurrentLevel
+        measYvar = pschannel.measureVoltage
+        tolerance = 0.02 # A
+        if step   is None: step = 0.1 # A
+        if tsleep is None: tsleep = 0.5 # s
+
+    else:
+        logger.error("'varName' can only be 'voltage' or 'current'")
+
+
+    # Get current values of V and I
+    xmeas = measXvar()
+    ymeas = measYvar()
+    #isOn = pschannel.getPowerSupply().isOn(pschannel.getChannel())
+    isOn = (measXvar() != 0 or measYvar() != 0)
+    
+    diff = target - xmeas
+    logging.debug(varName + " difference (target - meas): " + str(diff) + " " + xUnit)
+
+    # Decide whether ramping is finished or not
+    if abs(diff) <= tolerance / 2:
+        logger.info("ramping finished")
+        return xmeas
+
+
+    # determine direction of ramp
+    if diff < 0 and step > 0 or diff > 0 and step < 0 :
+        step = -step
+
+    logger.info("ramping from %.2g %s to %.2g %s in steps of %.2g %s" % (xmeas, xUnit, target, xUnit, step, xUnit))
+
+    while abs(xmeas) >= abs(target)+abs(step) or abs(xmeas) <= abs(target)-abs(step):
+        setXvar(xmeas+step)
+        time.sleep(tsleep)
+        xmeas = measXvar()
+        ymeas = measYvar()
+        logger.debug("PSU is on? " + str(isOn) + "; " + xVarName + ": " + str(xmeas) + " " + xUnit + "; " + yVarName + ": " + str(ymeas) + " " + yUnit)
+    
+    diff = target - xmeas
+    
+    if abs(diff) < abs(step):
+        logging.debug("--------------------")
+        logger.info("[%s, %s] = [%.2g %s, %.2g %s] " % (xVarName, yVarName, xmeas, xUnit, ymeas, yUnit))
+        ramp(xVarName, pschannel, target, step/5.)    
+
+
 def doivi(config, w, dbSink=""):
 
     if w == "iv":
@@ -83,7 +130,7 @@ def doivi(config, w, dbSink=""):
     ch = config[key]["target_channel"]
     ps = hw.getPowerSupplyChannel(ch["name"])
     if ps == None:
-        print("[ error ][ ivi ] change the config and try again!")
+        logger.error("change the config and try again!")
         exit(1)
 
     if w == "iv":
@@ -97,7 +144,7 @@ def doivi(config, w, dbSink=""):
         measYvar = ps.measureVoltage
 
 
-    print("Starting the %s scan..." % w)
+    logger.info("Starting the %s scan..." % w)
 
     if w == "iv": 
         ps.setCurrentProtect(ch["current_protection"])
@@ -127,30 +174,34 @@ def doivi(config, w, dbSink=""):
     data[yKeyOutUnit+"_Compliance"] = config[key]["target_channel"][yVarName+"_protection"]
 
     data[outputKey] = []
-    # < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < 
 
-    # Output to the terminal
-    # > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 
-    colWidths = "{0:8}{1:17}{2:20}{3:20}{4:20}{5:20}"
-    print(colWidths.format("# time", xVarName + "_Level", xVarName + "_SenseMean", xVarName + "_SenseStd", yVarName + "_SenseMean", yVarName + "_SenseStd"))
-    # < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < 
 
     xVar = ch["initial_" + xVarName]
     step = ch["step_size"]
 
     startX = measXvar()
+    #wasOn = ps.isOn()
+    wasOn = (measXvar() != 0 or measYvar() != 0)
 
-    # Go to the starting point
-    steps = np.linspace(startX, xVar, 10)
-    for e in steps:
-        setXvar(e)
-        time.sleep(1)
 
+    # Ramp to the starting point if PSU is already on
+    if wasOn:
+        ramp(xVarName, ps, xVar)#, 5, 1)
+    else:
+        setXvar(xVar)
+        ps.turnOn()
+
+    # Output to the terminal
+    # > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 
+    colWidths = "{0:8}{1:17}{2:20}{3:20}{4:20}{5:20}"
+    print(colWidths.format("# time", xVarName + "_Level", xVarName + "_SenseMean", xVarName + "_SenseStd", yVarName + "_SenseMean", yVarName + "_SenseStd"))
+    # < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < 
 
     while (xVar - ch["final_" + xVarName])* step/abs(step) <= 0:
 
         setXvar(xVar)
-        ps.turnOn()
+        if w == "vi":
+            ps.turnOn()
         
         time.sleep(ch["sleeping_time_per_step_s"])
 
@@ -166,7 +217,7 @@ def doivi(config, w, dbSink=""):
             yVarPerStep.append(measY)
 
             if measY > ch[yVarName + "_protection"]:
-                print("Reached " + yVarName + " protection value")
+                logger.warning("Reached " + yVarName + " protection value")
                 break
         else:
 
@@ -208,22 +259,25 @@ def doivi(config, w, dbSink=""):
             xVar += step
 
             # turn everything off (power-cycle the PS)
-            #ps.turnOff()
+            if w == "vi":
+                ps.turnOff()
+
             continue
         break
 
-
-    # Go back to the point before the scans
-    steps = np.linspace(measXvar(), startX, 10)
-    for e in steps:
-        setXvar(e)
-        time.sleep(1)
-
+    with open(args.outfile+"_"+w+".json", "w") as f:
+        json.dump(data, f, indent=4)
+        
+    if w == "iv":
+        # ramp HV outside of IV curve according to module testing document
+        # 2V/s for 3D, 5V/s for planar
+        ramp(xVarName, ps, startX)#, 5, 1)
+        if not wasOn:
+            ps.turnOff()
 
     powerPassiveChannels(config, key, "turnOff")
 
-    with open("output_"+w+".json", "w") as f:
-        json.dump(data, f, indent=4)
+
 
     
 
@@ -255,14 +309,14 @@ def toInfluxDB(points, dbSink, host='localhost', port=8086):
 
         # If auth is enabled, ask the user for his/her password
         if "authorization failed" in str(e):
-            print("[ warn ] Input the password for user \"{}\" in InfluxDB.\n" 
+            logger.warning("Input the password for user \"{}\" in InfluxDB.\n" 
                   "         If you don\'t want to input the password in the future until\n"
                   "         you close your current bash session use \n"
                   "                  \"export INFLUXDBPWD=yourPassword\".".format(usr))
             try:
                 pwd = getpass.getpass()
-            except:
-                print()
+            except Exception as e:
+                logger.error(e)
                 sys.exit(1)
 
     # And connect again.
@@ -279,8 +333,8 @@ def toInfluxDB(points, dbSink, host='localhost', port=8086):
     except exceptions.InfluxDBClientError as e:
 
         # If not, let the user know what's happening and exit.
-        print("[ error ] Received error from InfluxDB: {}".format(e))
-        print("[ info ] Please specify the db connectivity parameters "
+        logger.error("Received error from InfluxDB: {}".format(e))
+        logger.info("Please specify the db connectivity parameters "
                 "\"database\", and also \"username\", " 
                 "\"host\" and \"port\" in the .\"influxdb_cfg\" section in" 
                 "the provided DCS config file. Make sure the provided username and password are correct.\n")
@@ -290,11 +344,15 @@ def toInfluxDB(points, dbSink, host='localhost', port=8086):
     try:
         client.write_points(points)
     except exceptions.InfluxDBClientError as e:
-        print("[ error ] Received error from InfluxDB: {}".format(e))
+        logger.error("Received error from InfluxDB: {}".format(e))
         sys.exit(1)
 
 
 if __name__ == "__main__":
+    
+    coloredlogs.install(level="INFO") ### controls availability of colored logs
+    logger = verboselogs.VerboseLogger('ivi')
+
 
     parser = argparse.ArgumentParser()
     parser.add_argument(
@@ -306,8 +364,9 @@ if __name__ == "__main__":
     parser.add_argument(
         "-j",
         "--json",
-        required=True,
-        help="path to iviscan.json",
+        required=False,
+        default="configs/lr_iviscan.json",
+        help="path to iviscan.json. Default is \"configs/lr_iviscan.json\"",
     )
     parser.add_argument(
         "-e",
@@ -315,8 +374,23 @@ if __name__ == "__main__":
         required=True,
         help="powersupply.json Configuration file with the power supply definition",
     )
-
+    parser.add_argument(
+        "-o",
+        "--outfile",
+        required=False,
+        default="output",
+        help="output file name without file extension. Will be saved in .json format. Default is \"output\"",
+    )
+    parser.add_argument(
+        "-u",
+        "--upload",
+        required=False,
+        action="store_true",
+        help="If set will upload data to influxDB. \"influxdb_cfg\" required in powersupply.json",
+    )
+    
     args = parser.parse_args()
+    logger.debug(args)
 
     # - - - - - - - - - -
     with open(args.json) as f:
@@ -339,20 +413,16 @@ if __name__ == "__main__":
             try:
                 import _labRemote as labRemote
             except:
-                print("Couldn't find the labRemote Python libraries. Make sure to add them to your $PYTHONPATH first by either doing")
-                print()
-                print("     export PYTHONPATH=/path/to/labRemote/build/lib:$PYTHONPATH")
-                print()
-                print("  or writing \"/path/to/labRemote/build/lib\" in \"" + args.equip + "\"")
-                print()
-                print("And make sure also that you have previously built labRemote enabling the Python bindings (cmake3 -DUSE_PYTHON=on)")
+                logger.error("Couldn't find the labRemote Python libraries")
+                logger.info("Make sure to add them to your $PYTHONPATH first by either doing")
+                logger.info("    export PYTHONPATH=/path/to/labRemote/build/lib:$PYTHONPATH")
+                logger.info("    or writing \"/path/to/labRemote/build/lib\" in \"" + args.equip + "\"")
+                logger.info("Also make sure labRemote is built with Python bindings (cmake3 -DUSE_PYTHON=on)")
                 exit(1)
 
-
-
-    uploadToInflux = False
-    if uploadToInflux:
-        #dbSink = psConfig["influxdb_cfg"]
+    
+    if args.upload:
+        dbSink = psConfig["influxdb_cfg"]
         pass
     else:
         dbSink = ""