Skip to content

Instantly share code, notes, and snippets.

@timvisee
Created September 3, 2015 16:52
Show Gist options
  • Select an option

  • Save timvisee/45edd873ecb3cfb35e0d to your computer and use it in GitHub Desktop.

Select an option

Save timvisee/45edd873ecb3cfb35e0d to your computer and use it in GitHub Desktop.
A reaction wheel controller example by Tim Visee
# -*- coding: utf-8 -*-
"""
Reaction wheel controller, by Tim Visee.
@author: Tim Visee
"""
import serial
import time
""" Connection serial COM port. """
CONNECTION_COM = "COM4"
""" Connection serial baud rate. """
CONNECTION_BAUD = 115200
class ReactionWheelController:
""" ReactionWheelController.
Class to control a reaction wheel.
"""
""" Command to get current speed in RPM. """
COMMAND_SPEED_GET = "s"
""" Command to set current raw speed. """
COMMAND_SPEED_SET = "S"
""" Command to set current mode. """
COMMAND_MODE_SET = "M"
""" Delay between commands send to the wheel. """
COMMAND_DELAY = 0.25
""" Serial instance. """
ser = None
""" Current or last known mode. """
currentMode = None
""" Current or last known speed in RPM. """
currentSpeedRpm = 0
def __init__(self, connect):
""" Constructor.
:type: bool
:param connect: True to automatically connect to the wheel.
:return: None
"""
# Connect
if connect:
self.connect()
def connect(self):
""" Connect to the reaction wheel.
:return: None
"""
# Open the serial port
self.ser = serial.Serial(CONNECTION_COM, CONNECTION_BAUD,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.25,
xonxoff=False,
writeTimeout=0.25)
def is_connected(self):
""" Check weather the reaction wheel is connected.
:rtype: bool
:return: True if connected, False if not
"""
# Make sure the serial port is defined
if self.ser is None:
return False
# Check and return whether the serial port is open
return self.ser.isOpen()
def get_mode_cache(self):
""" Get the last known mode from the wheel.
:rtype: int
:return: Last known mode from the wheel
"""
# Return the last known mode
return self.currentMode
def set_mode(self, mode):
""" Set the mode of the reaction wheel.
:type: int
:param mode: The preferred reaction wheel mode, from 0 to 5.
:return: None
"""
# Send the mode command until the correct mode is selected
while self.get_mode_cache() is not mode:
# Send the mode command
self.send_command(self.COMMAND_MODE_SET)
# Process all current input to get the mode value
self.process_input()
def get_speed_rpm(self):
""" Get the current speed in RPM of the wheel.
:rtype: int
:return: Current speed in RPM.
"""
# Send the speed get command
self.send_command(self.COMMAND_SPEED_GET)
# Process the input
self.process_input()
# Return the speed value
return self.get_speed_rpm_cache()
def get_speed_rpm_cache(self):
""" Get the last known speed in RPM from the wheel.
:rtype: int
:return: Last known speed in RPM from the wheel.
"""
# Return the last known speed in RPM
return self.currentSpeedRpm
def set_speed_raw(self, speed):
""" Set the raw speed of the wheel.
:type: int
:param speed: Raw wheel speed.
:return: None
"""
# Send the set speed command
self.send_command(self.COMMAND_SPEED_SET)
# Send the speed value with proper formatting
self.send_command("%05d\n" % (speed,))
def send_command(self, command):
""" Send a command to the reaction wheel.
Note: This method will hold the thread for a while.
:type: string
:param command: Command to write.
:return: None
"""
try:
# Write the command
self.ser.write(command)
# Show a status message
print("[Send] %s" % command.strip())
except serial.SerialTimeoutException:
# Print error message
print("[ERROR] Failed to write command to wheel! (%s)" % command)
# Sleep so the command can process
time.sleep(self.COMMAND_DELAY)
def process_input(self):
""" Process all incoming data from the reaction wheel.
:return: None
"""
# Make sure the wheel is connected
if not self.is_connected():
return False
# Process all input
while self.ser.inWaiting():
# Read the line
line = self.ser.readline()
# Trim the line
line = line.strip()
# Skip empty lines (such as blank lines with \n)
if len(line) is 0:
continue
# Print the received value
print("[Received] %s" % line)
# Process mode set command
if "Mode set to:" in line:
# Remove the unnecessary bit and trim the value
line = line.replace("Mode set to:", "")
line = line.strip()
# Convert the value to a string, set the current mode
self.currentMode = int(line)
# Process speed get command
if ("Speed:" in line) and ("RPM" in line):
# Remove the unnecessary bit and trim the value
line = line.replace("Speed:", "").replace("RPM", "")
line = line.strip()
# Convert the value to a string, set the current speed in RPM
self.currentSpeedRpm = int(line)
# Create a reaction wheel instance and connect
print("Connecting...")
wheel = ReactionWheelController(True)
print("Connected!")
# Set the wheel mode
print("Setting reaction wheel mode to 4...")
wheel.set_mode(4)
print("Reaction wheel mode set!")
# Set the wheel RPM
print("Setting wheel speed to 140 RPM...")
wheel.set_speed_raw(140)
print("Wheel speed set!")
# Loop and retrieve the speed in RPM, print it to the console afterwards
while True:
# Get the current wheel speed
wheelSpeed = wheel.get_speed_rpm()
# Print the current wheel speed
print("Current speed: %i RPM" % wheelSpeed)
time.sleep(0.5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment