Skip to content

Commit

Permalink
Update library from testing with treadmill
Browse files Browse the repository at this point in the history
Inclination control working
  • Loading branch information
wsarce committed Jun 5, 2022
1 parent 17ccc1e commit fcbf3da
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,4 @@ dmypy.json

# Pyre type checker
.pyre/
Woodway Protocols Interface Board OEM SB.xls
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ a_port, b_port = find_treadmills(a_sn=a_sn, b_sn=b_sn)
if a_port is not None and b_port is not None:
print("Split belt treadmill found on ports", a_port, "and", b_port)
sb = SplitBelt(a_port, b_port)
sb = SplitBelt(a_port.name, b_port.name)
sb.start_belts(True, False, True, False)
print("Belt A set to 2 MPH and belt B set to -2 MPH.")
sb.set_speed(2.0, -2.0)
print("Set incline to 20%")
sb.set_elevations(20.0)
time.sleep(10)
print("Split belt speed:", sb.get_speeds())
print("Split belt incline:", sb.get_elevations())
print("Belt A set to -2 MPH and belt B set to 2 MPH.")
sb.set_speed(-2.0, 2.0)
# sb.set_speed(-2.0, 2.0)
time.sleep(10)
print("Split belt speed:", sb.get_speeds())
sb.stop_belts()
Expand Down
8 changes: 6 additions & 2 deletions examples/split_belt_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@

if a_port is not None and b_port is not None:
print("Split belt treadmill found on ports", a_port, "and", b_port)
sb = SplitBelt(a_port, b_port)
sb = SplitBelt(a_port.name, b_port.name)
sb.start_belts(True, False, True, False)
print("Belt A set to 2 MPH and belt B set to -2 MPH.")
sb.set_speed(2.0, -2.0)
print("Set incline to 20%")
sb.set_elevations(20.0)
time.sleep(10)
print("Split belt speed:", sb.get_speeds())
print("Split belt incline:", sb.get_elevations())
print("Belt A set to -2 MPH and belt B set to 2 MPH.")
sb.set_speed(-2.0, 2.0)
# sb.set_speed(-2.0, 2.0)
time.sleep(10)
print("Split belt speed:", sb.get_speeds())
sb.stop_belts()
Expand Down
66 changes: 48 additions & 18 deletions pywoodway/treadmill.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Treadmill:
"""
Class object to control a single treadmill belt. Should be compatible with all Woodway treadmills.
"""

def __init__(self, comport):
"""
Connects to the comport specified, stops the treadmill, and sets the control variables.
Expand All @@ -83,6 +84,8 @@ def __init__(self, comport):
self.forward = False
self.reverse = False
self.sending = False
self.treadmill_state = None
self.last_error = None

def close(self):
"""
Expand All @@ -100,16 +103,17 @@ def test_treadmill(self):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
command = bytearray()
command.append(TreadmillCommands.TEST_COMMS)
print(command)
self.comport.write(command)
return_code = self.comport.read(1)
if return_code == TreadmillReturns.TEST_COMMS:
print("State:", self.comport.read(1))
self.treadmill_state = self.comport.read(1)
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Test Treadmill Command {command}")
return False

def get_fw_rev(self):
Expand All @@ -119,6 +123,8 @@ def get_fw_rev(self):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
command = bytearray()
command.append(TreadmillCommands.GET_FW_REV)
self.comport.write(command)
Expand All @@ -128,7 +134,7 @@ def get_fw_rev(self):
fw_rev = (fw_bytes[0] << 24) | (fw_bytes[1] << 16) | (fw_bytes[2] << 8) | fw_bytes[3]
return fw_rev
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Get FW Rev {command}")
return False

def start_belt(self, timer):
Expand All @@ -139,6 +145,8 @@ def start_belt(self, timer):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
if timer:
command = bytearray()
command.append(TreadmillCommands.START_BELT_TIMER)
Expand All @@ -148,7 +156,7 @@ def start_belt(self, timer):
self.running = True
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Start Belt Timer {command}")
return False
else:
command = bytearray()
Expand All @@ -159,7 +167,7 @@ def start_belt(self, timer):
self.running = True
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Start Belt Timer {command}")
return False

def set_speed(self, mph):
Expand All @@ -170,6 +178,8 @@ def set_speed(self, mph):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
if isinstance(mph, float):
if mph > 29.9:
raise ValueError("Set speed is too high, speed must be below 29.9 MPH.")
Expand All @@ -188,14 +198,14 @@ def set_speed(self, mph):
command.append(ord('0'))
mph_digits = [ord(i) for i in str(mph)]
for digit in mph_digits:
if digit != 46:
if digit not in [46, 45]:
command.append(digit)
self.comport.write(command)
return_code = self.comport.read(1)
if return_code == TreadmillReturns.SET_SPEED:
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Set Belt Speed {command}")
return False
else:
raise ValueError("Parameter invalid - mph must be a float!")
Expand All @@ -208,6 +218,8 @@ def get_speed(self):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
command = bytearray()
command.append(TreadmillCommands.GET_SPEED)
self.comport.write(command)
Expand All @@ -221,7 +233,7 @@ def get_speed(self):
speed = -speed
return speed
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Get Belt Speed {command}")
return False

def set_elevation(self, elevation):
Expand All @@ -232,6 +244,8 @@ def set_elevation(self, elevation):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
if isinstance(elevation, float):
if elevation > 29.9:
raise ValueError("Over elevation, max inclination is 29.9%.")
Expand All @@ -251,7 +265,7 @@ def set_elevation(self, elevation):
if return_code == TreadmillReturns.SET_ELEVATION:
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Set Belt Elevation {command}")
return False
else:
raise ValueError("Elevation must be a float.")
Expand All @@ -264,19 +278,22 @@ def get_elevation(self):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
command = bytearray()
command.append(TreadmillCommands.GET_ELEVATION)
self.comport.write(command)
return_code = self.comport.read(1)
if return_code == TreadmillReturns.GET_SPEED:
if return_code == TreadmillReturns.GET_ELEVATION:
elevation_bytes = self.comport.read(4)
elevation = float((elevation_bytes[0] - 48) * 100.0) + \
float((elevation_bytes[1] - 48) * 10.0) + \
float((elevation_bytes[2] - 48)) + \
float((elevation_bytes[3] - 48) / 10.0)
return elevation
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Get Elevation {command}")
print(self.last_error)
return False

def stop_belt(self):
Expand All @@ -286,6 +303,8 @@ def stop_belt(self):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
command = bytearray()
command.append(TreadmillCommands.AUTO_STOP)
self.comport.write(command)
Expand All @@ -294,7 +313,7 @@ def stop_belt(self):
self.running = False
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Stop Belt {command}")
return False

def disengage_belt(self):
Expand All @@ -304,6 +323,8 @@ def disengage_belt(self):
"""
if self.comport is not None:
if self.comport.isOpen():
self.comport.flushInput()
self.comport.flushOutput()
command = bytearray()
command.append(TreadmillCommands.DISENGAGE_BELT)
self.comport.write(command)
Expand All @@ -312,14 +333,15 @@ def disengage_belt(self):
self.running = False
return True
else:
print("Something went wrong, code:", return_code)
self.last_error = (return_code, f"Disengage Belt {command}")
return False


class SplitBelt:
"""
Class to control the Woodway split belt treadmill. Wraps two instances of the Treadmill class.
"""

def __init__(self, comport_a, comport_b):
"""
Initializes the A and B belt comports.
Expand Down Expand Up @@ -358,9 +380,8 @@ def set_speed(self, a_mph, b_mph):
:param b_mph: float: speed of belt B in MPH, max is 29.9 MPH.
:return: bool: True if successful, False if failed.
"""
if self.belt_a.set_speed(a_mph):
if self.belt_b.set_speed(b_mph):
return True
self.belt_a.set_speed(a_mph)
self.belt_b.set_speed(b_mph)
return False

def stop_belts(self):
Expand All @@ -378,12 +399,21 @@ def get_speeds(self):
"""
return [self.belt_a.get_speed(), self.belt_b.get_speed()]

def set_elevations(self, elevation):
"""
Sets the elevation of both belts
:param elevation:
:return:
"""
self.belt_a.set_elevation(elevation)
# self.belt_b.set_elevation(b_elevation)

def get_elevations(self):
"""
Gets the elevation of the belts.
:return: np-list: First element is belt A elevation, second element is belt B elevation
"""
return [self.belt_a.get_elevation(), self.belt_b.get_elevation()]
return self.belt_a.get_elevation() # [self.belt_a.get_elevation(), self.belt_b.get_elevation()]

def get_fw_revs(self):
"""
Expand Down
12 changes: 9 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from setuptools import setup, find_packages

setup(name='pyWoodway',
version='0.1',
version='0.2.1',
url='https://github.com/Munroe-Meyer-Institute-VR-Laboratory/pyWoodway',
author='Walker Arce',
author_email='[email protected]',
description='Communicate with your Woodway treadmill in your Python scripts.',
packages=find_packages(),
# packages=find_packages(),
long_description=open('README.md').read(),
zip_safe=False)
zip_safe=False,
license='MIT',
packages=['pywoodway'],
install_requires=[
'pyserial'
],
)

# python setup.py bdist_wheel
# pip3 install pdoc3
Expand Down

0 comments on commit fcbf3da

Please sign in to comment.