Created
September 3, 2015 16:52
-
-
Save timvisee/45edd873ecb3cfb35e0d to your computer and use it in GitHub Desktop.
A reaction wheel controller example by Tim Visee
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- 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