From 259c56dbd65594ddc43643869be87e1b574ce5b3 Mon Sep 17 00:00:00 2001 From: martins055 Date: Wed, 18 May 2022 12:33:24 +0100 Subject: [PATCH 1/3] Added info in header Added linux librairies Added 2do list --- Code/Stimulator/libs/linux/_rehamovelib.so | Bin 0 -> 156048 bytes Code/Stimulator/libs/{ => linux}/rehamove.py | 0 Code/Stimulator/libs/linux/rehamovelib.py | 210 +++++++++++++++ .../libs/{ => windows}/_rehamovelib.pyd | Bin Code/Stimulator/libs/windows/rehamove.py | 240 ++++++++++++++++++ .../libs/{ => windows}/rehamovelib.py | 0 Code/Stimulator/stimulator_test.py | 101 ++++---- 7 files changed, 506 insertions(+), 45 deletions(-) create mode 100755 Code/Stimulator/libs/linux/_rehamovelib.so rename Code/Stimulator/libs/{ => linux}/rehamove.py (100%) mode change 100755 => 100644 create mode 100644 Code/Stimulator/libs/linux/rehamovelib.py rename Code/Stimulator/libs/{ => windows}/_rehamovelib.pyd (100%) create mode 100755 Code/Stimulator/libs/windows/rehamove.py rename Code/Stimulator/libs/{ => windows}/rehamovelib.py (100%) mode change 100755 => 100644 Code/Stimulator/stimulator_test.py diff --git a/Code/Stimulator/libs/linux/_rehamovelib.so b/Code/Stimulator/libs/linux/_rehamovelib.so new file mode 100755 index 0000000000000000000000000000000000000000..e8c559f05234c423fdd69e6e8c03c84843487d5c GIT binary patch literal 156048 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 bJtun6a=VHi5>fw~pOpGvQbthKU*Z1*2}uw) literal 0 HcmV?d00001 diff --git a/Code/Stimulator/libs/rehamove.py b/Code/Stimulator/libs/linux/rehamove.py old mode 100755 new mode 100644 similarity index 100% rename from Code/Stimulator/libs/rehamove.py rename to Code/Stimulator/libs/linux/rehamove.py diff --git a/Code/Stimulator/libs/linux/rehamovelib.py b/Code/Stimulator/libs/linux/rehamovelib.py new file mode 100644 index 0000000..2732024 --- /dev/null +++ b/Code/Stimulator/libs/linux/rehamovelib.py @@ -0,0 +1,210 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 3.0.12 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + +from sys import version_info as _swig_python_version_info +if _swig_python_version_info >= (2, 7, 0): + def swig_import_helper(): + import importlib + pkg = __name__.rpartition('.')[0] + mname = '.'.join((pkg, '_rehamovelib')).lstrip('.') + try: + return importlib.import_module(mname) + except ImportError: + return importlib.import_module('_rehamovelib') + _rehamovelib = swig_import_helper() + del swig_import_helper +elif _swig_python_version_info >= (2, 6, 0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_rehamovelib', [dirname(__file__)]) + except ImportError: + import _rehamovelib + return _rehamovelib + try: + _mod = imp.load_module('_rehamovelib', fp, pathname, description) + finally: + if fp is not None: + fp.close() + return _mod + _rehamovelib = swig_import_helper() + del swig_import_helper +else: + import _rehamovelib +del _swig_python_version_info + +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. + +try: + import builtins as __builtin__ +except ImportError: + import __builtin__ + +def _swig_setattr_nondynamic(self, class_type, name, value, static=1): + if (name == "thisown"): + return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name, None) + if method: + return method(self, value) + if (not static): + if _newclass: + object.__setattr__(self, name, value) + else: + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + + +def _swig_setattr(self, class_type, name, value): + return _swig_setattr_nondynamic(self, class_type, name, value, 0) + + +def _swig_getattr(self, class_type, name): + if (name == "thisown"): + return self.this.own() + method = class_type.__swig_getmethods__.get(name, None) + if method: + return method(self) + raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name)) + + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except __builtin__.Exception: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except __builtin__.Exception: + class _object: + pass + _newclass = 0 + +class RehamoveDevice(_object): + __swig_setmethods__ = {} + __setattr__ = lambda self, name, value: _swig_setattr(self, RehamoveDevice, name, value) + __swig_getmethods__ = {} + __getattr__ = lambda self, name: _swig_getattr(self, RehamoveDevice, name) + __repr__ = _swig_repr + __swig_setmethods__["device"] = _rehamovelib.RehamoveDevice_device_set + __swig_getmethods__["device"] = _rehamovelib.RehamoveDevice_device_get + if _newclass: + device = _swig_property(_rehamovelib.RehamoveDevice_device_get, _rehamovelib.RehamoveDevice_device_set) + __swig_setmethods__["battery"] = _rehamovelib.RehamoveDevice_battery_set + __swig_getmethods__["battery"] = _rehamovelib.RehamoveDevice_battery_get + if _newclass: + battery = _swig_property(_rehamovelib.RehamoveDevice_battery_get, _rehamovelib.RehamoveDevice_battery_set) + __swig_setmethods__["mode"] = _rehamovelib.RehamoveDevice_mode_set + __swig_getmethods__["mode"] = _rehamovelib.RehamoveDevice_mode_get + if _newclass: + mode = _swig_property(_rehamovelib.RehamoveDevice_mode_get, _rehamovelib.RehamoveDevice_mode_set) + __swig_setmethods__["current"] = _rehamovelib.RehamoveDevice_current_set + __swig_getmethods__["current"] = _rehamovelib.RehamoveDevice_current_get + if _newclass: + current = _swig_property(_rehamovelib.RehamoveDevice_current_get, _rehamovelib.RehamoveDevice_current_set) + __swig_setmethods__["pulse_width"] = _rehamovelib.RehamoveDevice_pulse_width_set + __swig_getmethods__["pulse_width"] = _rehamovelib.RehamoveDevice_pulse_width_get + if _newclass: + pulse_width = _swig_property(_rehamovelib.RehamoveDevice_pulse_width_get, _rehamovelib.RehamoveDevice_pulse_width_set) + + def __init__(self): + this = _rehamovelib.new_RehamoveDevice() + try: + self.this.append(this) + except __builtin__.Exception: + self.this = this + __swig_destroy__ = _rehamovelib.delete_RehamoveDevice + __del__ = lambda self: None +RehamoveDevice_swigregister = _rehamovelib.RehamoveDevice_swigregister +RehamoveDevice_swigregister(RehamoveDevice) + + +def open_port(port_name): + return _rehamovelib.open_port(port_name) +open_port = _rehamovelib.open_port + +def close_port(r): + return _rehamovelib.close_port(r) +close_port = _rehamovelib.close_port + +def initialize_low_level(r): + return _rehamovelib.initialize_low_level(r) +initialize_low_level = _rehamovelib.initialize_low_level + +def stop_low_level(r): + return _rehamovelib.stop_low_level(r) +stop_low_level = _rehamovelib.stop_low_level + +def pulse(r, channel, current, pulse_width): + return _rehamovelib.pulse(r, channel, current, pulse_width) +pulse = _rehamovelib.pulse + +def custom_pulse(r, channel, num_points, c0, w0, c1, w1, c2, w2, c3, w3, c4, w4, c5, w5, c6, w6, c7, w7, c8, w8, c9, w9, c10, w10, c11, w11, c12, w12, c13, w13, c14, w14, c15, w15): + return _rehamovelib.custom_pulse(r, channel, num_points, c0, w0, c1, w1, c2, w2, c3, w3, c4, w4, c5, w5, c6, w6, c7, w7, c8, w8, c9, w9, c10, w10, c11, w11, c12, w12, c13, w13, c14, w14, c15, w15) +custom_pulse = _rehamovelib.custom_pulse + +def change_mode(r, mode): + return _rehamovelib.change_mode(r, mode) +change_mode = _rehamovelib.change_mode + +def set_pulse_data(r, current, pulse_width): + return _rehamovelib.set_pulse_data(r, current, pulse_width) +set_pulse_data = _rehamovelib.set_pulse_data + +def run(r, channel, period, total_milliseconds): + return _rehamovelib.run(r, channel, period, total_milliseconds) +run = _rehamovelib.run + +def midlevel_start(r, channel, period): + return _rehamovelib.midlevel_start(r, channel, period) +midlevel_start = _rehamovelib.midlevel_start + +def midlevel_update(r): + return _rehamovelib.midlevel_update(r) +midlevel_update = _rehamovelib.midlevel_update + +def midlevel_end(r): + return _rehamovelib.midlevel_end(r) +midlevel_end = _rehamovelib.midlevel_end + +def get_version(): + return _rehamovelib.get_version() +get_version = _rehamovelib.get_version + +def get_battery(r): + return _rehamovelib.get_battery(r) +get_battery = _rehamovelib.get_battery + +def get_mode(r): + return _rehamovelib.get_mode(r) +get_mode = _rehamovelib.get_mode + +def get_current(r): + return _rehamovelib.get_current(r) +get_current = _rehamovelib.get_current + +def get_pulse_width(r): + return _rehamovelib.get_pulse_width(r) +get_pulse_width = _rehamovelib.get_pulse_width + +def battery_request(r): + return _rehamovelib.battery_request(r) +battery_request = _rehamovelib.battery_request +# This file is compatible with both classic and new-style classes. + + diff --git a/Code/Stimulator/libs/_rehamovelib.pyd b/Code/Stimulator/libs/windows/_rehamovelib.pyd similarity index 100% rename from Code/Stimulator/libs/_rehamovelib.pyd rename to Code/Stimulator/libs/windows/_rehamovelib.pyd diff --git a/Code/Stimulator/libs/windows/rehamove.py b/Code/Stimulator/libs/windows/rehamove.py new file mode 100755 index 0000000..21bf4db --- /dev/null +++ b/Code/Stimulator/libs/windows/rehamove.py @@ -0,0 +1,240 @@ +import rehamovelib + +class Rehamove: + + current_version = "v1.6" + + channel0 = ['r', 'red'] + channel1 = ['b', 'blue'] + channel2 = ['g1', 'gray1', 'grey1', 'black'] + channel3 = ['g2', 'gray2', 'grey2', 'white'] + + MODE_LOW_LEVEL = 0 + MODE_MID_LEVEL = 1 + + def __init__(self, port_name): + self.rehamove = rehamovelib.open_port(port_name) + self.mode = 0 + + def version(self): + c_version = rehamovelib.get_version() + print("Rehamove Version: Python-side " + str(Rehamove.current_version) + ", C-side " + str(c_version)) + return Rehamove.current_version + + def get_mode(self): + result = rehamovelib.get_mode(self.rehamove) + return result + + def get_current(self): + result = rehamovelib.get_current(self.rehamove) + return result + + def get_pulse_width(self): + result = rehamovelib.get_pulse_width(self.rehamove) + return result + + def info(self): + mode = self.get_mode() + current = self.get_current() + pulse_width = self.get_pulse_width() + + if mode == Rehamove.MODE_LOW_LEVEL: + return "Rehamove device in low-level mode. Mid-level pulse is set to {} mA and {} us.".format(current, pulse_width) + elif mode == Rehamove.MODE_MID_LEVEL: + return "Rehamove device in mid-level mode. Mid-level pulse is set to {} mA and {} us.".format(current, pulse_width) + else: + return "Rehamove info() ERROR!" + + def get_channel(self, channel): + chosen_channel = channel + if isinstance(channel, str): + channel = channel.lower() + if channel in Rehamove.channel0: + chosen_channel = 0 + elif channel in Rehamove.channel1: + chosen_channel = 1 + elif channel in Rehamove.channel2: + chosen_channel = 2 + elif channel in Rehamove.channel3: + chosen_channel = 3 + else: + chosen_channel = 0 # Default + elif isinstance(channel, int): + if channel < 0 and channel > 3: + chosen_channel = 0 # Default + else: + chosen_channel = 0 + return chosen_channel + + def pulse(self, channel, current, pulse_width): + if self.rehamove == None: + print("python Rehamove pulse() ERROR! Rehamove object does not exist.") + return -1 + chosen_channel = self.get_channel(channel) + result = rehamovelib.pulse(self.rehamove, chosen_channel, current, pulse_width) + if result != 0: + print("python Rehamove pulse() ERROR!") + return -1 + else: + print("python Rehamove pulse() sent.") + return 0 + + def custom_pulse(self, channel, points_array): + if self.rehamove == None: + print("python Rehamove custom_pulse() ERROR! Rehamove object does not exist.") + return -1 + chosen_channel = self.get_channel(channel) + original_length = len(points_array) + num_points = len(points_array) + # Error handling (warning) if too many points. + if num_points > 16: + print("python Rehamove custom_pulse() WARNING! Maximum of 16 points allowed, truncating points array.") + num_points = 16 + + # Error handling (exception) if malformed points. + try: + for i in range(0, num_points): + current = points_array[i][0] + pulse_width = points_array[i][1] + except: + print("python Rehamove custom_pulse() ERROR! Malformed points array, should be: [ (current0, pulse_width0), (current1, pulse_width1), ... ]") + return -1 + + # Handle if the user supplies less than 16 points: fill up empty points in the array. + remaining_points = 16 - num_points + for _ in range(0, remaining_points): + points_array.append((0.0, 0)) + + # Get all of our point data. + c0, w0 = points_array[0][0], points_array[0][1] + c1, w1 = points_array[1][0], points_array[1][1] + c2, w2 = points_array[2][0], points_array[2][1] + c3, w3 = points_array[3][0], points_array[3][1] + c4, w4 = points_array[4][0], points_array[4][1] + c5, w5 = points_array[5][0], points_array[5][1] + c6, w6 = points_array[6][0], points_array[6][1] + c7, w7 = points_array[7][0], points_array[7][1] + c8, w8 = points_array[8][0], points_array[8][1] + c9, w9 = points_array[9][0], points_array[9][1] + c10, w10 = points_array[10][0], points_array[10][1] + c11, w11 = points_array[11][0], points_array[11][1] + c12, w12 = points_array[12][0], points_array[12][1] + c13, w13 = points_array[13][0], points_array[13][1] + c14, w14 = points_array[14][0], points_array[14][1] + c15, w15 = points_array[15][0], points_array[15][1] + + result = rehamovelib.custom_pulse(self.rehamove, chosen_channel, original_length, c0, w0, c1, w1, c2, w2, c3, w3, c4, w4, c5, w5, c6, w6, c7, w7, c8, w8, c9, w9, c10, w10, c11, w11, c12, w12, c13, w13, c14, w14, c15, w15) + if result != 0: + print("python Rehamove custom_pulse() ERROR!") + return -1 + else: + print("python Rehamove custom_pulse() sent.") + return 0 + + def battery(self): + if self.rehamove == None: + print("python Rehamove ERROR! Rehamove object does not exist.") + return -1 + result = rehamovelib.battery_request(self.rehamove) + if result != 0: + print("python Rehamove battery() ERROR!") + return -1 + else: + battery_level = rehamovelib.get_battery(self.rehamove) + print("python Rehamove battery(): " + str(battery_level) + "%") + return battery_level + + def change_mode(self, mode): + if self.rehamove == None: + print("python Rehamove change_mode() ERROR! Rehamove object does not exist.") + return -1 + result = rehamovelib.change_mode(self.rehamove, mode) + if result != 0: + print("python Rehamove change_mode() ERROR!") + return -1 + else: + print("python Rehamove change_mode(): Changed mode to " + str(mode) + ".") + self.mode = mode + return 0 + + def set_pulse(self, current, pulse_width): + if self.rehamove == None: + print("python Rehamove set_pulse() ERROR! Rehamove object does not exist.") + return -1 + result = rehamovelib.set_pulse_data(self.rehamove, current, pulse_width) + if result != 0: + print("python Rehamove set_pulse() ERROR!") + return -1 + else: + print("python Rehamove set_pulse(): Set pulse current to " + str(current) + " and pulse width to " + str(pulse_width) + ".") + return 0 + + def run(self, channel, period, total_milliseconds): + if self.rehamove == None: + print("python Rehamove run() ERROR! Rehamove object does not exist.") + return -1 + if self.mode != Rehamove.MODE_MID_LEVEL: + print("python Rehamove run() ERROR! Mode must be set to mid-level.") + return -1 + chosen_channel = self.get_channel(channel) + result = rehamovelib.run(self.rehamove, chosen_channel, period, total_milliseconds) + if result != 0: + print("python Rehamove run() ERROR!") + return -1 + else: + print("python Rehamove run(): Completed.") + return 0 + + def start(self, channel, period): + if self.rehamove == None: + print("python Rehamove start() ERROR! Rehamove object does not exist.") + return -1 + if self.mode != Rehamove.MODE_MID_LEVEL: + print("python Rehamove start() ERROR! Mode must be set to mid-level.") + return -1 + chosen_channel = self.get_channel(channel) + result = rehamovelib.midlevel_start(self.rehamove, chosen_channel, period) + if result != 0: + print("python Rehamove start() ERROR!") + return -1 + else: + print("python Rehamove start(): Completed.") + return 0 + + def update(self): + if self.rehamove == None: + print("python Rehamove update() ERROR! Rehamove object does not exist.") + return -1 + if self.mode != Rehamove.MODE_MID_LEVEL: + print("python Rehamove update() ERROR! Mode must be set to mid-level.") + return -1 + result = rehamovelib.midlevel_update(self.rehamove) + if result != 0: + print("python Rehamove update() ERROR!") + return -1 + else: + print("python Rehamove update(): Completed.") + return 0 + + def end(self): + if self.rehamove == None: + print("python Rehamove end() ERROR! Rehamove object does not exist.") + return -1 + if self.mode != Rehamove.MODE_MID_LEVEL: + print("python Rehamove end() ERROR! Mode must be set to mid-level.") + return -1 + result = rehamovelib.midlevel_end(self.rehamove) + if result != 0: + print("python Rehamove end() ERROR!") + return -1 + else: + print("python Rehamove end(): Completed.") + return 0 + + def __del__(self): + # Only close the port if we have a Rehamove object to close + if self.rehamove != None: + result = rehamovelib.close_port(self.rehamove) + if result != 0: + print("python Rehamove close_port() ERROR!") + diff --git a/Code/Stimulator/libs/rehamovelib.py b/Code/Stimulator/libs/windows/rehamovelib.py similarity index 100% rename from Code/Stimulator/libs/rehamovelib.py rename to Code/Stimulator/libs/windows/rehamovelib.py diff --git a/Code/Stimulator/stimulator_test.py b/Code/Stimulator/stimulator_test.py old mode 100755 new mode 100644 index 4feecdb..249ab54 --- a/Code/Stimulator/stimulator_test.py +++ b/Code/Stimulator/stimulator_test.py @@ -1,45 +1,56 @@ -# -*- coding: utf-8 -*- -""" -https://github.com/humancomputerintegration/rehamove-integration-lib - -Notes: - - does not run on university computer that restricts access to USB/COM ports from scripts - - the pre-compiled python library for windows that is available on github requires python 3.7 (otherwise recompile) - - keep using the low-level mode, to send individual pulses -""" -# Debug: clear variables of IDE -from IPython import get_ipython -try: __IPYTHON__ -except: pass -else: get_ipython().run_line_magic('reset','-sf') - -# imports (load pre-compiled windows library in python3.7) -import sys, os -dirpath = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(dirpath+'\\libs') -import rehamove - -# Detect which COM port is in use -comPort = '' -from serial.tools import list_ports -ports = list_ports.comports() -for port, desc, hwid in sorted(ports): - if 'PID=0403:6014' in hwid: # this is the ID of our rehamove - # if it's a match, we save the COM port number - comPort = port - -# create instance -r = rehamove.Rehamove(comPort) - -# get info -r.info() -r.battery() -r.version() - -# set to low-level mode to control each individual pulse -r.change_mode(0) - -# send pulse -r.pulse("blue", 30, 50) # cable_color, milliAmps, duration in microseconds - - +# -*- coding: utf-8 -*- +""" +The python wrapper is coming from: https://github.com/humancomputerintegration/rehamove-integration-lib + # please read the license and limitations + +Notes: + - had to disable USB sleep in power settings on a windows laptop + - one of the usb port is not working reliably (need to use the left port on ABD's laptop) + - the pre-compiled python library for windows that is available on github requires python 3.7 (otherwise recompile) + - keep using the low-level mode, to send individual pulses + +2do: + - make anaconda env including serial-tool + - include test to load the lib. windows/linux + - add a loop to wait for the hardware to be connected + +""" + +# Debug: clear variables of IDE +from IPython import get_ipython +try: __IPYTHON__ +except: pass +else: get_ipython().run_line_magic('reset','-sf') + +# imports (load pre-compiled windows library in python3.7) +import sys, os +dirpath = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(dirpath+'\\windows\\libs') # windows +#sys.path.append(dirpath+'/libs/linux') # linux (need to give permission in /dev/ttyUSB*) +import rehamove + +# Detect which COM port is in use +comPort = '' +from serial.tools import list_ports +ports = list_ports.comports() +for port, desc, hwid in sorted(ports): + if 'PID=0403:6014' in hwid: # this is the ID of our rehamove + # if it's a match, we save the COM port number + comPort = port + +# create instance +r = rehamove.Rehamove(comPort) + +# get info +r.info() +r.battery() +r.version() + +# set to low-level mode to control each individual pulse +r.change_mode(0) + +# send pulse +r.pulse("blue", 30, 50) # cable_color, milliAmps, duration in microseconds + + + From 3ba15c499385a20096ab3965f9831d2de707319a Mon Sep 17 00:00:00 2001 From: martins055 <50996055+martins055@users.noreply.github.com> Date: Wed, 18 May 2022 13:16:03 +0100 Subject: [PATCH 2/3] Create README.MD --- Code/Stimulator/README.MD | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Code/Stimulator/README.MD diff --git a/Code/Stimulator/README.MD b/Code/Stimulator/README.MD new file mode 100644 index 0000000..f9ca488 --- /dev/null +++ b/Code/Stimulator/README.MD @@ -0,0 +1,8 @@ +## The python wrapper is coming from: the [Human Computer Integration Lab, Chicago](https://github.com/humancomputerintegration/rehamove-integration-lib) + # please read the license and limitations + +## Notes: +- had to disable USB sleep in power settings on a windows laptop to keep the rehastim working reliably +- one of the usb port is not working reliably, even with the new power settings (need to use the left port on ABD's laptop) +- the pre-compiled python library for windows that is available on github requires python 3.7 (otherwise recompile) +- keep using the low-level mode, to send individual pulses From 744d49f76a072f80f4d18f15db14a3ad47e27356 Mon Sep 17 00:00:00 2001 From: martins055 Date: Fri, 20 May 2022 13:45:01 +0100 Subject: [PATCH 3/3] Added example for mid-level mode --- Code/Stimulator/stimulator_test.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Code/Stimulator/stimulator_test.py b/Code/Stimulator/stimulator_test.py index 249ab54..d2acc35 100644 --- a/Code/Stimulator/stimulator_test.py +++ b/Code/Stimulator/stimulator_test.py @@ -46,11 +46,14 @@ r.battery() r.version() -# set to low-level mode to control each individual pulse -r.change_mode(0) - -# send pulse -r.pulse("blue", 30, 50) # cable_color, milliAmps, duration in microseconds +# low-level mode: control each individual pulse +r.change_mode(0) # set to low-level mode to control each individual pulse +r.pulse("blue", 30, 50) # send pulse: cable_color, milliAmps, duration in microseconds + +# mid-level mode: continuous stimulation that we need to update +# r.change_mode(1) +# r.set_pulse(5, 200) # Set the pulse used in mid-level mode +# r.run("blue", 100, 10000) # Run that set pulse every 100 ms for 10s total