FACULTY OF ENGINEERING AND DESIGN

IMEE FINAL YEAR BEng PROJECT REPORT

CubeSat Docking Simulator

William Easdown

May 10th 2019

“I certify that I have read and understood the entry on Plagiarism, duplication of one’s own work and Cheating on the Quality Assurance Code of Practice QA53 and in my Departmental Student Handbook. All material in this assignment is my own work, except where I have indicated with appropriate references. I agree that, in line with Regulation 15.3(e), if requested I will submit an electronic copy of this work for submission to a Plagiarism Detection Service for quality assurance purposes.”

Author’s signature: ………………………….

Supervisor: Dr Rob Wortham

Assessor: Dr Pejman Iravani

CUBESAT DOCKING SIMULATOR FINAL REPORT

AUTHOR: WILLIAM EASDOWN SUPERVISOR: DR ROB WORTHAM ASSESSOR: DR PEJMAN IRAVANI

Figure 1 - Render of the CubeSat Docking Simulator final CAD model

i Abstract This document presents a CubeSat Docking Simulator that has been designed and manufactured for the author’s Bachelor of Engineering (BEng) Final Year Project (FYP) at the University of Bath. Air tables, air bearings and arms are currently used widely in the space sector for modelling of satellite motion, but this report presents a Mecanum-wheeled system as an alternative. The Simulator system consists of a robot and controller, with the robot using stepper motor-driven Mecanum wheels for omnidirectional motion across the plane of a floor. The robot and controller both use Raspberry Pi computers to control their electronics and for communication between the two devices. They are both powered by lithium polymer batteries. Code for both devices is written in Python. Design and manufacture used a range of techniques, such as computer aided design, 3D printing and the use of traditional tools such as drills and mills.

Testing of the system was broken into subsections. The controller worked fully as intended, but robot propulsion could not be achieved. It is suspected by the author that this was due to a software issue, which will be investigated in future work. However, the system still met the majority of its requirements. Design decisions taken during the project included manufacturing printed circuit boards at home and changing the model of Raspberry Pi computer that was used in the controller.

Acknowledgements I would like to thank Dr Rob Wortham for his excellent support as my supervisor during the project, including very useful technical assistance. Feedback from Dr Pejman Iravani has been extremely helpful in my design and documentation process. Zoë Babb has also given me fantastic support throughout the project.

ii Table of Contents Abstract ...... ii Acknowledgements ...... ii List of Figures ...... vi List of Tables ...... vi List of Acronyms ...... vii 1 Introduction ...... 1 2 Literature Review ...... 1 2.1 Current Methods of Docking Simulation ...... 1 2.1.1 Air Tables and Air Bearings ...... 1 2.1.2 Robot Arms ...... 1 2.1.3 Omni-Directional ...... 2 2.2 Mecanum Wheels ...... 2 2.3 Similar Systems ...... 2 2.3.1 Robots ...... 2 2.3.2 Controllers ...... 3 3 Design, Manufacture and Testing ...... 4 3.1 System Overview...... 4 3.1.1 Robot ...... 6 3.1.1.1 Power ...... 6 3.1.1.2 Propulsion ...... 7 3.1.1.3 Control ...... 8 3.1.1.4 Software ...... 8 3.1.1.4.1 Function Definitions ...... 9 3.1.1.4.1.1 motor_speeds(motor1_speed, motor2_speed, motor3_speed, motor4_speed, dms) ...... 9 3.1.1.4.1.2 pulse(xPin) ...... 9 3.1.1.4.1.3 stop(allpins) ...... 9 3.1.1.4.1.4 shutdown(allpins) ...... 9 3.1.1.4.1.5 stepper_drive(allpins, speeds) ...... 9 3.1.1.4.2 Initialisation ...... 10 3.1.1.4.2.1 Libraries and Functions ...... 10 3.1.1.4.2.2 Variables ...... 10 3.1.1.4.2.3 Motors ...... 11 3.1.1.4.2.4 Buttons ...... 11 3.1.1.4.3 Main Loop ...... 11 3.1.2 Controller ...... 12

iii 3.1.2.1 Case ...... 13 3.1.2.2 Control ...... 13 3.1.2.3 Power ...... 13 3.1.2.4 User Interface...... 14 3.1.2.5 Software ...... 15 3.2 Design and Manufacture Methods ...... 15 3.2.1 Overall System ...... 15 3.2.2 Robot ...... 16 3.2.3 Controller ...... 16 3.2.3.1 Case ...... 16 3.2.3.2 Electronics ...... 17 3.3 Safety ...... 18 3.4 Testing ...... 18 3.4.1 Controller ...... 18 3.4.1.1 Screen ...... 18 3.4.1.2 Power Supply ...... 18 3.4.1.3 Software ...... 18 3.4.1.4 Overall Controller Testing ...... 18 3.4.2 Robot ...... 18 3.4.2.1 Power ...... 18 3.4.2.2 Propulsion ...... 18 3.4.2.3 Control ...... 19 3.4.2.4 Overall Robot Testing ...... 19 4 Results and Analysis ...... 20 4.1 Compliance with Requirements ...... 20 4.1.1 Compliant Requirements ...... 21 4.1.2 Non-Compliant Requirements ...... 21 4.1.3 Not Tested Requirements ...... 21 5 Discussion ...... 23 5.1 Design Decisions ...... 23 5.1.1 Deliberate Non-Compliance with Translation Speed Requirement (PRO-0010) ...... 23 5.1.2 Change of Controller Raspberry Pi Model ...... 23 5.1.3 Self-Tapping Screws for Controller Assembly ...... 23 5.1.4 Controller Printed Circuit Board (PCB) Manufacture ...... 23 5.2 Design Shortcomings...... 23 5.2.1 Non-Functioning Motion ...... 23 5.2.2 Controller Case Screwhead Lip ...... 24 5.3 Descoping ...... 25

iv 5.4 Cost ...... 25 6 Conclusions ...... 26 7 Future Work ...... 27 8 References ...... 28 Appendix A – Requirements Specification ...... 32 A.1 Mechanical Requirements ...... 32 A.2 Electrical Requirements ...... 32 A.3 Control Requirements ...... 32 A.4 Propulsion Requirements ...... 32 A.5 Operation Requirements ...... 33 A.6 Interface Requirements ...... 33 A.7 Safety Requirements ...... 33 Appendix B - Robot Code ...... 34 B.1 Motion Code ...... 34 B.2 Camera Code ...... 38 Appendix C - Controller Code...... 40 C.1 Shutdown Python File ...... 40 C.2 Shutdown Shell Script ...... 40 Appendix D – Mechanical Drawings ...... 41 D.1 Robot Chassis ...... 41 Appendix E – Bills of Materials ...... 42 E.1 Robot ...... 42 E.2 Controller ...... 43 Appendix F – PCB Manufacture Process ...... 44 F.1 Preparation ...... 44 F.2 Exposure ...... 44 F.3 Development ...... 44 F.4 Etching...... 45 F.5 Clean up ...... 45 F.6 Safety ...... 46 Appendix G – Setting Buck Converter Output Voltage ...... 47

v List of Figures Figure 1 - Render of the CubeSat Docking Simulator final CAD model ...... i Figure 2 - The European Proximity Operations Simulator (EPOS) 2.0 in use at the German Aerospace Center (DLR) [8]...... 2 Figure 3 - An example of an omni wheel [10]...... 2 Figure 4 - Render showing the overall CubeSat Docking Simulator system...... 4 Figure 5 - The final CubeSat Docking Simulator system...... 5 Figure 6 - Render of the robot ...... 6 Figure 7 - Robot internal wiring...... 7 Figure 8 - A Mecanum wheel with attached hub as used on the robot...... 8 Figure 9 - Robot code flowchart ...... 12 Figure 10 - Render of the controller ...... 13 Figure 11 - The controller shows a live video feed from the robot camera and has buttons to control the robot motion...... 14 Figure 12 - Robot CAD in Fusion 360...... 15 Figure 13 - Controller CAD in Fusion 360...... 15 Figure 14 – Some parts were modelled from scratch, such as the wheel hubs (a) and stepper motors (b)...... 16 Figure 15 - The Form command in Autodesk Fusion 360 was used to model the controller case...... 17 Figure 16 - Autodesk EAGLE was used to model the controller button PCBs...... 17 Figure 17 - The motor speed variables in the robot can be varied by the controller...... 24 Figure 18 - Controller case cross section showing on the left the lack of a screwhead lip...... 24 Figure 19 - Robot chassis mechanical drawing ...... 41 Figure 20 - Copper layout printed on a projector transparency sheet...... 44 Figure 21 - A board after development...... 45 Figure 22 - The completed boards after drilling and clean up...... 45

List of Tables Table 1 - Compliance matrix ...... 20 Table 2 - Cost breakdown ...... 25 Table 3 - Robot BOM ...... 42 Table 4 - Controller BOM ...... 43

vi List of Acronyms

ABS Acrylonitrile Butadiene Styrene BEng Bachelor of Engineering BOM Bill of Materials CAD Computer-Aided Design CDS CubeSat Docking Simulator DLR Deutsches Zentrum für Luft- und Raumfahrt DOF Degrees of Freedom DPST Double Pole, Single Throw EPOS European Proximity Operations Simulator ESA European Space Agency FYP Final Year Project GPIO General-Purpose Input/Output GPU Graphical Processing Unit GUI Graphical User Interface HIL Hardware-in-the-Loop IC Integrated Circuit IP Internet Protocol LCD Liquid Crystal Display LED Light-Emitting Diode LiPo Lithium polymer mA milliamps mAh milliamp-hour OS Operating System PCB Printed Circuit Board PIXEL Pi Improved Xwindow Environment, Lightweight PPBR Project Plan and Background Review RAM Random-Access Memory rpm Revolutions per minute ROV Remotely-Operated Vehicle SBC Single-Board Computer SMD Surface-Mount Device TFT Thin-Film Transistor USB Universal Serial Bus UV Ultraviolet VNC Virtual Network Computing WLAN Wireless Local Area Network

vii 1 Introduction For his final year project (FYP) at the University of Bath, this author chose to design and build a CubeSat Docking Simulator (CDS). This document follows on from the previous Project Plan and Background Review (PPBR) [1] and presents the completed hardware and software. This report also describes how the system was designed, built and tested. Test results are supplied and various shortcomings of the project and design decisions that were made are discussed. Potential future work on the project is outlined before a series of appendices.

2 Literature Review The following literature review describes the reasoning behind the project, why certain design decisions were taken and how the completed system compares to others currently available. Some of the material presented here is the same as was presented in the PPBR [1].

2.1 Current Methods of Docking Simulation Hardware-in-the-loop (HIL) simulation is used across industry and academia as an accurate method to model system dynamics.

2.1.1 Air Tables and Air Bearings As discussed in the PPBR, a common method currently used for ground-based docking simulation is the air table. For example, Ivanov et al. [2] used an air table for development of a motion control algorithm for approach with a noncooperative target .

A similar system design uses an air bearing, where an air pump system provides a layer of air under a disc, so it can glide across a smooth granite surface. A paper by Rybus et al. [3] details the use of these air bearings to verify simulations relating to use of satellite manipulators.

However, both air tables and air bearings suffer from only being able to operate on a single plane. Some systems, such as at the University of Surrey [4] also use high pressure nitrogen thruster systems on the satellite models to propel them across the plane, adding unwanted complexity and cost. These are issues that the author’s CubeSat Docking System aims to alleviate.

2.1.2 Robot Arms An alternative method of rendezvous and docking simulation uses one or more robot arms. These allow modelling of all six degrees of freedom (DOF) in the motion of the approaching spacecraft. Two arms can be used together, as in a study by Ma, Flores-Abad and Boge [5], to allow the models of the interceptor and target spacecraft to move.

However, robot arms’ stiffness limits their ability to accurately simulate the dynamic response of satellites during contact and docking. A method of improving the simulation to address this has been presented by Zebenay, Boge, Lampariello and Choukroun [6].

National and international space agencies also make use of robot arms for satellite docking simulation. The German Aerospace Center’s (DLR) European Proximity Operations Simulator (EPOS) 2.0 in Oberpfaffenhofen, Germany, is one example and is shown in Figure 2. The European Space Agency’s (ESA) Telerobotics and Haptics Laboratory includes a robot arm for small scale simulations [7].

1

Figure 2 - The European Proximity Operations Simulator (EPOS) 2.0 in use at the German Aerospace Center (DLR) [8].

2.1.3 Omni-Directional Robots Examples of the use of omni-directional robots, whether using Mecanum wheels or omni wheels (see Figure 3), are limited. However, an omni wheel robot has been used by a team in Ankara [9] for development of a satellite docking algorithm.

Figure 3 - An example of an omni wheel [10].

2.2 Mecanum Wheels Mecanum wheels are used in a variety of applications where the ability to translate in any direction is a design driver. They have been applied to forklift trucks [11], pipe inspection [12] and nuclear decommissioning [13].

2.3 Similar Systems 2.3.1 Robots Small robots featuring Mecanum wheels are a popular hobbyist project, with many examples available online [14] [15] [16]. However, large Mecanum-wheeled robots such as the KUKA omniMove [17] are also used in industry, for applications such as transportation of Airbus A380 fuselage sections [18].

2 2.3.2 Controllers The JXD s192k Trident controller by OpenROV [19] uses an tablet as a large screen. It has buttons arranged in a layout akin to that of a video game controller and is used to control an underwater remotely-operated vehicle (ROV). Other similar systems include the Smart Controller by drone manufacturer DJI [20] and the controller for Nintendo’s Wii U games console [21].

3 3 Design, Manufacture and Testing 3.1 System Overview The system has remained largely unchanged since the PPBR. However, more details of which specific parts have been used are included in the following sections, with a full parts list shown in Appendix E – .

Overall, the system includes an omnidirectional robot that represents the satellite under simulation, and a controller for the user to manually control it in real time. The robot, controller and their subsystems are detailed in the following sections.

Figure 4 - Render showing the overall CubeSat Docking Simulator system.

4

Figure 5 - The final CubeSat Docking Simulator system.

5 3.1.1 Robot

Figure 6 - Render of the robot

3.1.1.1 Power Electrical power is supplied by a 5 Ah lithium polymer (Li-Po) battery with a nominal voltage of 11.1 V [22]. The expected current draw of the Raspberry Pi computer (see Section 3.1.1.3 - Control) was up to around 700 milliamps (mA) [23] and other the components were expected to draw around a further 500 mA. This led to a 5 Ah battery being chosen to meet requirements ELE-0010 and OPS-0010. Before being distributed to the rest of the electronics, the battery output is routed through a double pole, single throw (DPST) latching rocker switch [24] and a 5 A fuse. This increases the robot safety: in an emergency, the user can throw the switch to totally isolate the robot’s power supply, or in the event of an overcurrent condition, the fuse will protect the battery to reduce the risk of fire.

The battery directly supplies the Vmotor input on the motor controllers (see Section 3.1.1.2 - Propulsion and below), but is passed through a buck converter [25] to supply the 5 V required by the Raspberry Pi (see Section 3.1.1.3 - Control). The buck converter was permanently set to the correct output voltage, as described in Appendix G – Setting Buck Converter Output Voltage.

The motor controller boards (see Section 3.1.1.3 - Control) can have their Vcc logic level supplied with any voltage between 2.7 V and 5.5 V. However, the level of the logic input pins (INA1, INA2, INB1, INB2 and STBY) must match that of Vcc. The Raspberry Pi uses 3.3 V logic [26], so Vcc must be supplied with 3.3 V. Thus, for each board Vcc is connected via a jumper wire to the 3.3 V distribution block (see below). The PWMA and PWMB inputs on the controller boards are also held to Vcc, as specified in the TB6612FNG datasheet [27].

6 Battery voltage

Buck converter

3.3 V

Battery

Raspberry Pi

Figure 7 - Robot internal wiring.

Pieces of non-fused terminal block are used for power distribution. The battery is initially fed into a two-way terminal block to allow easy attachment of wires that take the power to the cut-off switch and fuse in the lid of the robot.

A large 10-way block is used to distribute the battery voltage. Five of the positions are used for ground, while the other five distribute the positive battery voltage. One side of the block holds wire loops which are used to connect positions with the same voltage. The other side is used for connecting the inputs and outputs to the block. Input is provided by a pair of wires connected to the cut-off switch in the lid of the robot. Output wire pairs are connected to the buck converter and each of the motor controller boards. The controller boards take an input at the battery voltage to feed the Vmotor input of the TB6612FNG motor driver integrated circuit (IC).

A five-way terminal block is used to distribute the 3.3 V needed for the motor controller logic supply, Vcc. Like the 10-way block, this uses wire loops on one side to connect the terminals. On the other side of the block, a male to female jumper wire connects the block to the Raspberry Pi’s 3.3 V power output on the GPIO header. The other four terminals are connected to four male to female jumper wires that are connected to the Vcc pins on each of the four motor controller boards.

3.1.1.2 Propulsion Propulsion is provided by four 12 V unipolar stepper motors [28], each connected to a 100 mm Mecanum wheel [29] via a collet [30] and hub [31]. Each stepper motor is driven by a motor controller board [32] that uses dual H-bridges to supply the motor coils.

7

Figure 8 - A Mecanum wheel with attached hub as used on the robot.

3.1.1.3 Control Robot control is enabled by a Raspberry Pi 3 Model B+ [33] single-board computer (SBC) running the Raspbian operating system (OS). This uses 802.11ac wireless local area network (WLAN) connectivity (Wi-Fi) to communicate with the controller. The robot was setup as a Wi-Fi hotspot using a guide on the Raspberry website [34]. The controller automatically connects to the hotspot on boot. This enables commands to be sent directly to the robot from the controller. Relative to using an additional router to which both devices would connect, this removes the need for extra hardware and increases system security by removing a source of vulnerability. Details of how the code enables transmission of commands across the Wi-Fi link are included in Section 3.1.1.4.2.1 - Libraries and Functions.

A Raspberry Pi Camera Module v2 [35] is bolted to the front face of the robot chassis. This is controlled by a Python program, which is described in Section 3.1.1.4 - Software. The code sends a live video feed from the robot to the screen on the controller, for the user to view in real-time. Using the real-time feed to estimate the robot’s position and velocity and act accordingly, the user closes the control feedback loop. This allows the user to precisely control the robot’s motion.

Control signals are carried from the 40-pin General-Purpose Input/Output (GPIO) header on the Raspberry Pi to the motor controller boards by female to female jumper wires [36]. These carry the 3.3 V pulses sent by the motion code to the motor controller inputs, where they are amplified by the board’s dual H-bridges and sent to the motors.

3.1.1.4 Software The robot’s motion code was written in Python and is split into several functions. The full code listing can be found in Appendix B.1 - Motion Code. A flowchart of the motion code is shown in Figure 9. The various parts of the program are described in the following sections.

The camera code is contained in a separate file, a full listing of which can be found in Appendix B.2 - Camera Code. The code initialises a live feed, which the controller connects to, then initialises the camera to send its data over the live feed. The code was copied from a listing by Rui Santos [37], then modified to increase the frame rate. This is kept separate from the motion code so that if the motion code becomes caught in a loop or otherwise stops functioning as desired, the user can still see where the robot is facing so they can locate it if it is not within a line of sight.

8 3.1.1.4.1 Function Definitions This section, from line 7 to 159, defines all the functions to be used in the code, so they can be called later.

3.1.1.4.1.1 motor_speeds(motor1_speed, motor2_speed, motor3_speed, motor4_speed, dms) This function reads the status of each controller button in turn and, if it has been pressed, adjusts the list of motor speeds according to the type of motion that has been requested. In this way, the motor speeds are relative: they are all declared to be zero initially but are then increased or decreased to affect the type of motion required. For example, if the translate forwards button is pressed, all motor speeds will increase by the same amount (by the amount set by the dms variable), because a positive motor speed applied to each motor yields forward motion.

While setting the motor speeds, this function also checks that they have not already reached their limits. All motor speeds must lie within their range of -100% to +100%, so button presses only update a motor speed if it current lies within the range, to ensure it cannot take an unexpected value.

3.1.1.4.1.2 pulse(xPin) This function takes a pin, specified by the xPin argument, turns it on, waits for 30 µs, then turns the pin off before returning. The function is used within stepper_drive(allpins, speeds) to pulse the stepper motor pins.

3.1.1.4.1.3 stop(allpins) This function is called at the start of the main loop. If the off button is pressed, it sets the motor speeds to zero, then iterates through each pin of each motor (allpins), turning off each pin in turn. It then returns the motor speeds. To enable it to iterate through the list of pins, it takes this list as an argument.

3.1.1.4.1.4 shutdown(allpins) This function is called immediately after stop(allpins) at the start of the main loop. If the off button is held, it runs the stop function, disables the motor controllers by connecting their standby pins to ground, then runs the system shutdown -h now command to shut down the robot’s Raspberry Pi. Disabling the motor controllers ensures that the motors cannot be inadvertently driven during the shutdown process. To enable it to call the stop(allpins) function, this function also takes allpins as an argument.

3.1.1.4.1.5 stepper_drive(allpins, speeds) This function contains the main loop run by the code during operation. The function begins by setting a mode value, which determines which of two pulse sequences are to be used to drive the steppers. The first pulse sequence equates to a low speed, high torque mode of driving the steppers, with the other sequence resulting in high speed, low torque driving.

A stepCount variable and a stepCounter to count through it are then declared, with the count being equal to the length of the chosen sequence. A variable representing the direction of the steps is also declared and set to zero. A list holding the waitTime for each of the four motors is declared, with the initial times being set to zero.

The end of this function is an infinite loop. It starts by calling the stop(allpins)and shutdown(allpins) functions to check that the user has not requested the robot to cease its motion or to shut down entirely. Next, the speeds list of motor speeds is updated by calling motor_speeds(motor1_speed, motor2_speed, motor3_speed, motor4_speed, dms).

9 The code then enters a for loop where it iterates through each wheel. It firstly decides whether it is a wheel on the left or right of the robot and sets the step direction accordingly: for forward motion with positive speed, wheels on the left must rotate anticlockwise while wheels on the right rotate clockwise. The waitTime is set next. This uses a linear relationship to match the speed percentage to a waitTime in milliseconds.

A new for loop is then entered, still within the first. It iterates through the pins for each wheel, giving each pin a temporary name set by xPin. The pulse sequence set at the beginning of the function is then checked: if it is not zero for this motor pin, the pin is turned on, otherwise it is turned off. This completes the for loop.

Next, the stepCounter for the wheel is incremented by stepDir and is reset if at the end of its sequence. Finally, the code sleeps for the value of waitTime for the wheel in question: it is this interval between the pin pulses that determines the speed of each stepper motor.

3.1.1.4.2 Initialisation This section establishes the various libraries, variables and assignments needed for the functions to run.

3.1.1.4.2.1 Libraries and Functions Various libraries and functions from libraries are required for the code to run. This section of the code imports these libraries and functions.

The gpiozero library [38] by Ben Nuttall, Dave Jones and others, is used to interact with the Raspberry Pi’s GPIO pins. It is used to read the states of the controller buttons and to send pulses to the motor controllers to drive the stepper motors.

The line from gpiozero import Button imports the Button class for reading input from a button. This is used, along with the pin factory functionality described below, when initialising the controller buttons.

The Remote GPIO functionality enabled by gpiozero allows the pins on the controller Pi to be read wirelessly from the robot Pi, using the controller Pi’s Internet Protocol (IP) address. Before initialising the controller buttons, the controller Pi’s IP address is specified (on line 219) as the pin factory for the buttons. This pin factory is then used as an argument when declaring the buttons to link the buttons in the controller to the code in the robot. The button initialisation is described in more detail in as described in Section 3.1.1.4.2.4 - Buttons.

The sleep function is imported from the time library [39] to be used in stepper_drive(allpins, speeds). When called, this function causes the code to wait for an amount of time in seconds that is supplied to the function as an argument.

The call function is imported from the subprocess library [40] to be used in shutdown(). When called, the call function runs the command that is specified as an argument to the function. In this case, the argument is a command to immediately shutdown the robot’s Raspberry Pi.

3.1.1.4.2.2 Variables Four global variables are created to represent the speeds of each motor as a percentage of their maxima. A positive value for each motor speed is such that driving all fours motors at the same positive speed would cause the robot to drive straight forwards.

10 The dms variables sets the change in motor speed for each button press, where each button press represents a firing of the thrusters on the CubeSat that the robot is simulating. This value can be adjusted to represent lower or higher thrust thrusters on the satellite. Applying this updated speed to the motors is achieved through the stepper_drive(allpins, speeds) function.

3.1.1.4.2.3 Motors The motor initialisation section, from line 184 to 213, uses the OutputDevice function from the gpiozero library to declare each pin of each motor. The number of each pin is the BCM number for that pin in the GPIO header’s pinout [41]. Each motor’s pins are grouped into a list, then these lists are grouped into a list of lists of all the pins.

3.1.1.4.2.4 Buttons The buttons and their required pin factory are declared between lines 218 and 229. The factory variable is declared with the PIGPIOFactory class to store the controller’s IP address as the pin factory for the buttons. This variable can then easily be referred to as an argument when declaring the buttons.

The Button class in gpiozero is used for declaring buttons. The first argument is the pin on the Raspberry Pi to which the button is connected. This numbering does not follow the physical pin layout but rather the BCM numbering scheme used by the Pi’s processor. The second argument specifies the pin factory, which uses the factory variable declared beforehand. The third argument specifies the bounce time in seconds for the buttons. This adds software debouncing such that a single button press by the user is not interpreted by the code as multiple presses. The off button has a fourth argument that specifies the hold time in seconds. When the button is held for this length of time, Button.is_held becomes true, allowing code to be run dependent on whether the button is held. In this case, the shutdown(allpins) runs this check and triggers a shutdown of the robot if the off button is held.

3.1.1.4.3 Main Loop The main loop occurs within the stepper_drive(allpins, speeds) function, which is called on line 233 of the code. The loop serves to update the robot’s motion as per user requests. Full details of this loop are include in the description of the function definition – see Section 3.1.1.4.1.5 - stepper_drive(allpins, speeds).

11

Figure 9 - Robot code flowchart

The code to control the live video feed from the camera runs in a separate file so that if the motion code crashes, the live feed should still be visible. The live feed code was taken from the Random-Nerd- Tutorials GitHub repository by Rui Santos [42] and is shown in Appendix B.2 - Camera Code.

3.1.2 Controller The controller is the main method of user interaction with the CDS. It is where the user sends commands to the robot and views a live video feed from it. The controller’s subsystems are described in the following sections.

12

Figure 10 - Render of the controller

3.1.2.1 Case The case comprises two halves 3D printed in acrylonitrile butadiene styrene (ABS) plastic. It has holes for the buttons, on/off switch and charging port. The two halves are attached by up to six screws, although four have been found to provide adequate fastening.

3.1.2.2 Control The controller’s processor is a Raspberry Pi Model 3 A+ [43] SBC. This uses the same BCM2837B0 processor as found in the Model 3 B+ [44] used in the robot but has less random-access memory (RAM) and no graphical processing unit (GPU). It also has one Universal Serial Bus (USB) port instead of four. However, these reductions in specification were not considered limiting due to the simplicity of the code required to run on the controller (see Appendix C - Controller Code) and the corresponding level of processing power required.

The Pi 3A+ also features the same 2.4 GHz and 5 GHz 802.11b/g/n/ac Wi-Fi as the 3B+ used in the robot, allowing a wireless connection to be established between the two devices easily. The controller connects to the robot’s Wi-Fi hotspot automatically on boot, so data can be transferred bidirectionally and directly between the controller and robot.

A Raspberry Pi Zero W was originally to be used as the controller processor due to its low power consumption and small form factor. However, this was replaced for the current Pi 3A+ when it was discovered during testing that the Zero W was incompatible with the chosen screen. This change is described further in Section 5.1 - Design Decisions.

3.1.2.3 Power Electrical power is supplied to the controller by a 3.7 V 1200 mAh LiPo battery [45]. The output voltage from this is passed through a PowerBoost 1000 boost converter [46] to convert it to the 5.2 V needed to supply to Pi 3A+. The PowerBoost board can supply up to 1 A, which is sufficient to power the Pi and screen (see Section 3.1.2.4 - User Interface for details of the screen).

The PowerBoost also acts as a charger for the LiPo battery. A mobile phone charger or similar 5 V USB power supply is connected to the PowerBoost board, through the board’s USB Micro B connector,

13 illuminating a blue light emitting diode (LED) on the board. At the end of the charge cycle, a green LED illuminates to indicate that the battery is fully charged.

It was discovered during early testing that the screen remained illuminated even when the Raspberry Pi had been fully shut down. This was due to the 5 V input still being connected to it via the Pi’s micro USB port and General-Purpose Input/Output (GPIO) header. To address this, a switch was added to allow the user to connect the EN (enable) pin on the PowerBoost board to ground. This disables the PowerBoost’s TPS6109 boost converter IC, completely disconnecting the PowerBoost output from the input [47] and removing power from the Pi and screen. Thus, the screen can be turned off entirely to save battery once the Pi has been shut down using the onscreen menu.

3.1.2.4 User Interface The user interface for the controller consists of a 3.5 ” 480x320 pixel thin-film-transistor (TFT) liquid crystal display (LCD) touchscreen branded as PiTFT Plus [48], and seven 12 mm push switches [49] with yellow caps [50]. The screen displays the live video feed from the Raspberry Pi camera on the front of the robot, while the buttons are used to command the robot’s motion.

The four buttons on the right-hand side of the controller command the translation of the robot. The top of the four buttons commands forwards translation, the left commands left, right commands right and the bottom button commands backwards translation. These functions are labelled in Figure 11.

Figure 11 - The controller shows a live video feed from the robot camera and has buttons to control the robot motion.

The buttons are soldered to a pair of printed circuit boards (PCBs), which were manufactured at home. The reasoning behind this manufacture method is described in Section 5.1.4 - Controller Printed Circuit Board (PCB) Manufacture, with the process itself described in Appendix F – PCB Manufacture Process.

14 3.1.2.5 Software The controller uses the full version of the Raspbian operating system (OS), which provides a graphical user interface (GUI) and the PIXEL (Pi Improved Xwindow Environment, Lightweight) desktop environment. Upon boot, the Chromium web browser is automatically opened to the page showing the robot’s live video feed. The pigpio daemon [51] is also run at boot to enable the Remote GPIO functionality that sends button commands from the controller to the robot.

3.2 Design and Manufacture Methods The following sections describe the software and tools that were used in the design and manufacture of the CDS.

3.2.1 Overall System The robot and controller were modelled separately, with Autodesk’s Fusion 360 program [52] being used for the computer-aided design (CAD) process, as shown in Figure 12 and Figure 13. Files to be used in the robot or controller models were stored in a library in the same directory.

Figure 12 - Robot CAD in Fusion 360.

Figure 13 - Controller CAD in Fusion 360.

15 3.2.2 Robot Components (known as assemblies in other CAD programs) were used to group related parts together into groups such as Chassis, Propulsion or Control. Fusion 360’s integration with the McMaster-Carr part library [53] allowed fasteners to be imported to more accurately model the final design. CAD models for some parts, such as the wheel hubs and stepper motors, were not available, so were instead modelled from scratch. These models are shown in Figure 14. Other parts, such as the Raspberry Pi and its camera, were downloaded from the community-sourced CAD library GrabCAD [54].

(a) (b)

Figure 14 – Some parts were modelled from scratch, such as the wheel hubs (a) and stepper motors (b).

The holes in the chassis were marked out using masking tape, then cut using a pillar drill and filed smooth.

3.2.3 Controller 3.2.3.1 Case The case for the controller was modelled using the Form command in Fusion 360. This allowed a complex shape to be modelled without using many small extrudes and cuts. It enabled a smooth body to be created easily, the shape of which could be adjusted by dragging any face, edge or vertex, as shown in Figure 15. A line of symmetry was setup so that any edits to one side of the case would automatically be applied to the corresponding area on the other side.

16

Figure 15 - The Form command in Autodesk Fusion 360 was used to model the controller case.

The controller case was printed on one of the university’s UP BOX+ 3D printers [55] that used ABS plastic and the fused filament fabrication method to produce the case. Some of the support structure created during printed had to be removed using a milling machine for the controller’s internal components to fit. The case was printed in two halves, which were then screwed together using self- tapping screws. The reasoning behind using self-tapping screws over other attachment methods is described in Section 5.15.1 - Design Decisions. As well as for the screws, holes were designed into the case for charging and for the on/off switch.

3.2.3.2 Electronics The button PCBs were modelled in Autodesk EAGLE [56], with the designs then being pushed to Fusion 360 for integration into the overall controller design. Supports for the PCBs were modelled into the controller case and holes cut in the top of the case for the buttons to pass through.

Figure 16 - Autodesk EAGLE was used to model the controller button PCBs.

17 3.3 Safety System safety is of critical importance to avoid injury to the user or surrounding people. With this in mind, the robot and controller both include cut-off switches. On the robot, the switch totally isolates the battery from the rest of the robot, while on the controller the switch toggles the boost converter enable pin, disabling its output and powering off the controller.

A fuse is also included in the robot so that if an overcurrent condition occurs, the battery is protected, and the risk of fire reduced. The plastic box used for the robot chassis electrically insulates the user from the voltages within, with the same being true for the controller case.

3.4 Testing Controller subsystems were tested individually before integration into the final design, as described in the PPBR [1]. The robot subsystems could not easily be tested independently as the propulsion system and software were interdependent. However, final testing of the overall system was carried out to evaluate the entire system’s performance.

3.4.1 Controller 3.4.1.1 Screen The screen tests ensured that the screen could display an image at a resolution and brightness that was comfortable to read. The screen driver was installed on the Pi 3A+ and the screen tested on April 1st, 2019.

3.4.1.2 Power Supply To prepare for the power supply test, the LiPo battery was fully charged, as indicated by the charging status LED on the PowerBoost charger turning green. The controller, including the Raspberry Pi and screen, was then run solely from battery power, demonstrating that the battery could supply the necessary voltage and current for boot up and operation.

3.4.1.3 Software The controller’s software runs the necessary programs on boot. These include the Chromium web browser, which is automatically opened on a page showing the live video feed from the robot. This automatic feed opening was setup and tested on 1st April 2019, with it being tested at the same time as the screen (see Figure 11).

3.4.1.4 Overall Controller Testing Overall controller testing demonstrated that the buttons could be used to control the , while the user watched the live feed on the screen and the controller ran entirely on its own battery power. This test was completed successfully.

3.4.2 Robot 3.4.2.1 Power Before switching on the robot for the first time, all wiring connections were thoroughly checked against the pinouts of the Raspberry Pi and motor controllers to ensure that no mistakes had been made. The robot power system was tested by connecting the battery to the rest of electronics and switching the robot on, then visually checking that the Raspberry Pi was booting up and no damage had occurred to any components.

3.4.2.2 Propulsion The propulsion system was tested by running the motion code on the robot and controlling it with the controller. When the code was run, the stepper motors could be heard to tick, but would not turn.

18 This suggested a software issue with the motors not receiving pulses of the correct length or with the correct interval between pulses. The motors could not have been seized as their shafts can be turned by hand.

3.4.2.3 Control The control system testing for motion involved observing the motor speed variables and waitTimes in the Python shell (see Figure 17) and checking that these could be changed by pressing the controller buttons. This test was completed successfully. The robot reacted seemingly instantaneously to commands, but the exact latency could not be determined. This is discussed further in Section 4.1.3 - Not Tested Requirements. However, due to the propulsion system not functioning as intended, the robot’s control authority could not be fully tested.

The live video feed from the camera to the controller was tested separately to the motion code. This involved switching on the robot and controller, then waiting for the controller to automatically connect to the robot’s Wi-Fi hotspot and open the Chromium browser, showing the live feed. This completed successfully, as shown in Figure 11.

3.4.2.4 Overall Robot Testing Overall robot testing would have involved using the controller to drive the robot across a floor, testing the velocity and acceleration requirements. Further details of these tests are included in Section 4.1.3 - Not Tested Requirements. However, due to the robot’s propulsion system not functioning as intended, this testing series could not be performed.

19 4 Results and Analysis 4.1 Compliance with Requirements Compliance testing produced the results shown in Table 1. The requirement IDs and descriptions are taken from the Requirements Specification, which was modified from that presented in the PPBR [1]. The modifications are described below, with the full and updated Requirements Specification shown in Appendix A – Requirements Specification. The system was marked as compliant (C), non-compliant (NC), partially compliant (PC) or not tested (NT) with the respective requirement for each test. The test results or proposed procedures are described in Sections 4.1.1 to 4.1.3.

Requirement SAF-0010 – Battery isolation in the PPBR was found to be a duplicate of CON-0030 – Emergency stop and so was removed. SAF-0020 – Controller overcurrent cut-off was added to the new Requirements Specification after it was found that no requirement had been set for overcurrent protection in the controller. INT-0010 – Wireless connectivity was edited to remove the reference to payload code, as the CDS in its current form only uses one main file for system control. Requirements PRO-0010 – translation speed and PRO-0020 – rotation speed were reworded for clarity.

Table 1 - Compliance matrix

Requirement ID Requirement Description Date of Test Test Result (C/NC/PC/NT) MEC-0010 Dimensions not to exceed 40 cm length, 30 cm 10/5/19 C width or 30 cm height. MEC-0020 Mass of no more than 10 kg. 10/5/19 C ELE-0010 Battery capacity not to exceed 5 Ah. 21/4/19 C ELE-0020 Battery nominal voltage not to exceed 12 V. 21/4/19 C CON-0010 Control system to provide manual control of all 21/4/19 C robot motion. CON-0020 Control system to provide full rotational and 10/5/19 C translational control across plane of operation. CON-0030 Button or other mechanism to cut all robot power 21/4/19 C to be provided as an emergency stop. CON-0040 Newton’s First Law to be simulated to emulate lack 10/5/19 C of resistance from ground or air in space. CON-0050 Control system to exhibit a latency of no more than 10/5/19 NT 100 ms. CON-0060 Robot to include a forward-facing camera to allow 21/4/19 C the user to view its trajectory. CON-0070 Control to be capable of controlling robot and 10/5/19 C receiving live video from it at a distance of 5 m. PRO-0010 Robot to have a maximum translation speed of at 10/5/19 NT least 30 cm/s. PRO-0020 Robot to have a maximum rotation speed of at 10/5/19 NT least 70 deg/s. PRO-0030 Robot to have a minimum linear acceleration of 10 10/5/19 NT cm/s. PRO-0040 Robot to have a minimum angular acceleration of 10/5/19 NT 28 deg/s. OPS-0010 System (including robot and controller) shall have 10/5/19 C a minimum battery life of 60 minutes. OPS-0020 Robot to provide full speed motion on a surface 10/5/19 NT with a slope of 2 %.

20 INT-0010 System shall provide for wireless updates of 21/4/19 C onboard software. INT-0020 Any manual control of the system shall be through 21/4/19 C a wireless link. SAF-0010 Robot to include a method of electrically isolating 9/5/19 C its battery if current drawn exceeds 5 A. SAF-0020 Controller to include a method of electrically 10/5/19 NC isolating its battery if current drawn exceeds 3 A.

4.1.1 Compliant Requirements MEC-0010: the robot is 30 cm long, 32 cm wide and 16 cm tall. MEC-0020: the robot has a mass of 3.309 kg and the controller a mass of 346 g, for a total system mass of 3.655 kg. ELE-0010: the battery capacity is 5 Ah. ELE-0020: the battery has a nominal voltage of 11.1V. CON-0010: manual control of all robot motion is provided by the controller buttons. CON-0020: the control system allows rotation and translation speeds to be varied independently, limited by the maximum speeds of the motors. CON-0030: a cut-off switch is provided on the lid of the robot that totally electrically isolates the battery from the rest of the robot. CON-0040: the robot motion code drives the motors at constant speed unless commanded otherwise, maintaining the same robot velocity and adhering to Newton’s First Law. CON-0060: the robot includes a Raspberry Pi Camera Module v2 mounted to its front face to allow the user to view its trajectory. CON-0070: the robot responded to commands from a distance of five metres and the live video feed could still be seen on the controller screen. OPS-0010: during testing the controller was found to be the limiting factor in system battery life, lasting approximately two hours. INT-0010: the software on the controller and robot can be updated wirelessly by using virtual network computing (VNC) to remotely view the Raspberry Pis’ desktops. INT-0020: manual control is carried out over a Wi-Fi link. SAF-0010: a 5 A fuse is included in the robot that will isolate the battery if blown.

4.1.2 Non-Compliant Requirements SAF-0020: the controller includes a method of isolating the boost converter input from its output, but this is done manually and is not based on current.

4.1.3 Not Tested Requirements CON-0050: due to the non-real-time nature of the Raspberry Pi’s operating system, this requirement was difficult to test accurately. Theoretically, it could be tested by filming with a high-speed camera the user pressing the controller button and the robot moving in response. However, a very high framerate would be required to determine with certainty whether a latency of less than 100 ms had been observed. Hiring or purchasing a camera of this type was deemed out of the budget of this project. PRO-0010, PRO-0020, PRO-0030, PRO-0040: due to the non-functioning robot motion, these requirements could not be tested in time for the project conclusion. However, testing of the translation requirements would have involved traversing the robot across a grid of parallel lines 10cm apart and measuring with a high frame rate camera the time taken for the robot to travel between the lines. Thus, the speed and acceleration could be calculated. A similar test would have been carried out for the rotation requirements, but with the robot traversing a compass-like circle of lines rather

21 than a grid. A camera that could have been used for these tests is already in the possession of the author. OPS-0020: this requirement could also not be tested due to the non-functioning robot motion. The test for this requirement could have involved performing the translation and rotation tests on a disabled access ramp of between five and ten metres length, as these have a maximum gradient of 1 in 20, or 5 % [57]. The ramp would have been measured before testing to determine its precise gradient. Alternatively, a wooden slope could have been built to the 2 % requirement and used for testing instead.

22 5 Discussion 5.1 Design Decisions Throughout the project, several key design decisions were made, based on either the research of others or my own experience during development of the CDS.

5.1.1 Deliberate Non-Compliance with Translation Speed Requirement (PRO-0010) For this proof of concept system, the robot was knowingly designed using stepper motors that would make it non-compliant with the translation speed requirement (PRO-0010) of at least 30 cm/s. This was to avoid an even larger budget overrun due to having to buy expensive high-speed stepper motors. Cheap stepper motors were chosen that have a maximum speed of around 80 rpm, as opposed to the 360 rpm needed to meet the requirement. This decision does not affect the robot’s ability to demonstrate full freedom of translation and rotation, but rather simply limits its maximum velocity. Therefore, despite the individual requirement not being met, the overall project aims could still be fulfilled.

5.1.2 Change of Controller Raspberry Pi Model It was discovered on March 25th, 2019 that the controller PiTFT Plus display only showed a white screen on the Raspberry Pi Zero W that was being used in the controller at the time. However, it was fully functioning on the robot’s Pi 3B+. This suggested that part of the OS for the Zero W’s older BCM2835 processor [58]was incompatible with the display driver.

A Raspberry Pi 3 Model A+ was chosen to replace the Zero W. It has the same processor as the 3B+, making it compatible with the display, and has the same Wi-Fi and Bluetooth functionality as the Pi Zero W. Testing confirmed compatibility (see Section 3.4.1.1 - Screen). It has a bigger form factor, which resulted in changes to the controller case internal layout.

5.1.3 Self-Tapping Screws for Controller Assembly Self-tapping screws were chosen to attach the two halves of the controller case. Other threading method included direct modelling of threads in the printed part or using threaded inserts. However, research by Stefan Hermann [59] showed that modelled threads would potentially be much weaker, dependent on print direction. There was also uncertainty over the ability of the 3D printer to print at the resolution required for accurate threads of such a small size. Threaded brass inserts were considered but according to Hermann these would add cost for a small amount of strength gain.

5.1.4 Controller Printed Circuit Board (PCB) Manufacture Due to their design simplicity and to reduce lead time and cost significantly, the PCBs holding the controller buttons were made at home using the photoresist method. Manufacturing followed the process detailed in Appendix F – PCB Manufacture Process, with both boards being made simultaneously on the same piece of material to halve the process time. The process had to be repeated due to insufficient exposure time and poor-quality developer and etchant chemicals being used on the first board.

5.2 Design Shortcomings 5.2.1 Non-Functioning Motion Despite the robot’s motion code having been tested and proven to change the speed variables for each motor, this did not translate into moving motors. It is suspected that this is due to a software issue related to pulsing the stepper motors, as the motors can be heard ticking but do not rotate. However, the motor variables can be varied by pressing the buttons on the controller, as shown in Figure 17. This issue will be investigated further to fix its root cause.

23

Figure 17 - The motor speed variables in the robot can be varied by the controller.

5.2.2 Controller Case Screwhead Lip During assembly of the controller case, it was discovered that a design flaw had made attaching the two halves difficult. A flat face (lip) was needed in the bottom half of the case for the screwhead to press against. However, this lip was missed during the design process, meaning another solution had to be devised. The chosen solution was to use longer screws with wider heads that those originally intended, such that the screw extended the full length of the bore and the screwhead pressed against the outer surface of the controller case.

Figure 18 - Controller case cross section showing on the left the lack of a screwhead lip.

24 5.3 Descoping The watchdog timer that was suggested in the PPBR was descoped due to the time limitations of the project. With other safety features such as a manual cut-off switch and fuse having been implemented, it was felt that the watchdog timer would be a suitable item to descope. This is an item that would be added if future work on the project were to continue, after the robot motion had been established.

5.4 Cost The budget for the project was originally £250, as this is what the university would supply to fund it. However, this was flexible to an extent due to the author being willing to support the project with his own funds. Ultimately, after discussions over ownership of the project hardware, it was decided that the author would fully fund the project.

A breakdown of the project cost by system is shown in Table 2, with full Bills of Materials (BOMs) shown in Appendix E – .

Table 2 - Cost breakdown

System Cost (£) Robot Chassis 25.70 Robot Propulsion 249.16 Robot Control 4.99 Robot Power 38.57 Robot Fixings 24.87 Robot Total 343.29

Controller Case 25.00 Controller Control 80.65 Controller Power 24.70 Controller Fixings 2.39 Controller Total 132.74

Grand Total 476.03

25 6 Conclusions This document has presented the design, manufacture and test process that the author followed to produce a proof of concept robot and controller CubeSat Docking Simulator system. Other methods of docking simulation have been presented and analysed in the literature review, along with current research into Mecanum wheels and similar robot and controllers.

The system in its final form was then presented, with each subsystem being described in turn. The methods and tools used to manufacture the system were then described. A range of techniques have been used throughout the project, from mechanical and electrical CAD to 3D printing to milling, among others. Safety measures implemented in the system were described, followed by the procedures carried out during testing.

In the Results and Analysis section, a compliance matrix was shown. The system is fully compliant with the majority of its requirements, with some not testable due to hardware debugging taking longer than expected. Only one of the 24 requirements was marked as non-compliant and this would be easier to address in a future version of the system.

Discussion focussed on decisions made during the design phase and shortcomings of the final design. Decisions included changing the model of Raspberry Pi used in the controller, using self-tapping screws in the controller rather than other fixing methods, and manufacturing the controller PCBs at home. The main shortcoming with the complete system was the inability of the motors to turn, but the author is confident that the hardware is finalised and that given more for software debugging, full robot motion can be realised. The descoping of the watchdog timer suggested in the PPBR was discussed, as well as the project cost. The cost was higher than initially forecast but at no extra cost to the university, as the author has fully funded the project.

26 7 Future Work A key limitation of the system in its current form is that the CubeSat can only be modelled as travelling across the plane on which the robot drives. Vertical motion modelling can be added to a future robot version by adding a linear actuator to the top of the robot, to which a box representing the CubeSat would be mounted. This would avoid major changes to the control code as it would only necessitate the addition of one extra axis. In this way, the robot base, which this project represents, would be purely for propulsion across the floor plane. The CubeSat box would then be a sensor testbed, with the sensors inputting into the control code and HIL testing being made possible.

This idea could be expanded further by adding a pair of servos to the linear actuator, giving the CubeSat full six degrees of freedom (DOF) motion. The servo that enabled pitch control would be attached to the linear actuator, with the servo controlling roll attached to the arm of the pitch servo. In this way, the CubeSat could be translated up and down using the linear actuator but also pitched or rolled through 360 degrees to simulate a tumbling spacecraft or one that was aligning itself with an off-angle target.

Regarding safety, a good addition to the control code would be a routine to run the emergency stop function if the robot detects that it is no longer connected to the controller. This would act as a form of dead man switch to prevent a runaway robot scenario where the robot is functioning correctly but not under user control. In this scenario, the robot may be moving in a way that makes the emergency stop switch difficult to manually actuate, so the computer should also have a method of disabling the robot if this situation arises.

To greatly simplify the robot’s wiring, a future version would likely use a custom PCB for the four motor controllers and power distribution including buck converter. This would take the battery voltage as an input to a terminal block, then distribute the voltage to the four TB6612FNG motor controller ICs. The TB6612FNGs would have their outputs connected to four headers for the steppers to connect to. The board would include a female 40-pin header into which would be plugged a ribbon cable attached to the Raspberry Pi. This would mean that the only loose wires in the robot would be the battery input, the ribbon cable from the Pi to the board and the stepper input wires.

27 8 References

[1] W. Easdown, CubeSat Docking Simulator Project Plan and Background Review, Bath: William Easdown, 2019. [2] D. Ivanov, M. Koptev, M. Ovchinnikov, S. Tkachev, N. Proshunin and M. Shachkov, “Flexible Microsatellite Mock-Up Docking with Noncooperative Target on Air Table,” in 9th International Workshop on Satellite Constellations and Formation Flying, University of Colorado Boulder June 19-21, 2017, Boulder, CO, 2017. [3] T. Rybus, J. Nicolau-Kukliński, K. Seweryn, T. Barciński, M. Ciesielska, K. Grassmann, J. Grygorczuk, M. Karczewski, M. Kowalski, M. Krzewski, T. Kuciński, J. Lisowski, R. Przybyła, K. Skup, T. Szewczyk and R. Wawrzaszek, “New Planar Air-Bearing Microgravity Simulator for Verification of Space Numerical Simulations and Control Algorithms,” Warsaw. [4] E. McKenna, “AAReST Spacecraft Electro-magnetic Docking System,” University of Surrey, Guildford, 2015. [5] O. Ma, A. Flores-Abad and T. Boge, “Use of industrial robots for hardware-in-the-loop simulation of satellite rendezvous and docking,” Acta Astronautica, vol. 81, pp. 335-347, 2012. [6] M. Zebenay, T. Boge, R. Lampariello and D. Choukroun, “Satellite Docking Simulator Based on Hardware-in-the-Loop Hybrid Contact Model,” Weling, Germany, 2013. [7] J. Smisek and A. Schiele, “Small Scale Free Floating Simulator A Hybrid Approach,” ESA Telerobotics, Noordwijk, 2015. [8] DLR (CC-BY 3.0), “European Proximity Operations Simulator (EPOS) in Oberpfaffenhofen,” 29 April 2009. [Online]. Available: https://www.dlr.de/media/en/desktopdefault.aspx/tabid- 4986/8423_page-7//8423_read-13187. [Accessed 6 May 2019]. [9] Y. E. A. M. N. Uyar, M. C. Soydan, M. S. Harmankaya, F. Alan and B. Akbulut, “Developing and Modelling of Satellite Docking Algorithm,” Ankara. [10] RobotShop inc., “60mm Aluminum Omni Wheel,” RobotShop inc., [Online]. Available: https://www.robotshop.com/en/60mm-aluminum-omni-wheel.html. [Accessed 10 May 2019]. [11] OKTA Lift, “Products / Electricity Forklift / OLM 20-16 Mecanum Electric Forklift,” [Online]. Available: http://www.okta.com.tr/olm-20-16-mecanum-electric-forklift_14_en_u.html. [Accessed 6 May 2019]. [12] W. A. Blyth, D. R. W. Barr and F. R. y. Baena, “A Reduced Actuation Mecanum Wheel Platform for Pipe Inspection”. [13] The University of Manchester Dalton Nuclear Institute, “MIRRAX - 150,” [Online]. Available: http://uomrobotics.com/nuclear/roboticplatforms/autonomous%20exploration/mirrax150.h tml. [Accessed 20 April 2019]. [14] silver_a, “Mecanum Wheel Robot - Bluetooth Controlled,” Autodesk, Inc., [Online]. Available: https://www.instructables.com/id/Mecanum-wheel-robot-bluetooth-controlled/. [Accessed 10 May 2019]. [15] Makeblock Robotics, “How to Make a Mecanum Robot With Suspension,” Autodesk, Inc., [Online]. Available: https://www.instructables.com/id/How-to-Make-a-Mecanum-Robot- With-Suspension/. [Accessed 10 May 2019]. [16] J. Baichtal, “Sweet robot with mecanum wheels,” Maker Media, Inc., 29 April 2010. [Online]. Available: https://makezine.com/2010/04/29/sweet-robot-with-mecanum-wheels/. [Accessed 10 May 2019]. [17] KUKA AG, “KUKA omniMove,” KUKA AG, [Online]. Available: https://www.kuka.com/en- gb/products/mobility/mobile-platforms/kuka-omnimove. [Accessed 10 May 2019].

28 [18] KUKA - Robotics & Automation, “Airbus Uses KUKA omniMove Mobile Platform to Build the A380,” YouTube, LLC, 15 June 2016. [Online]. Available: https://www.youtube.com/watch?v=RZ_8xhCi72w. [Accessed 10 May 2019]. [19] OpenROV, “Trident Controller,” [Online]. Available: https://store.openrov.com/collections/trident-accessories/products/trident-controller. [Accessed 17 April 2019]. [20] DJI, “DJI Smart Controller,” DJI, [Online]. Available: https://www.dji.com/uk/smart-controller. [Accessed 10 May 2019]. [21] Nintendo, “A unique console and controller full of exciting experiences the whole family can enjoy,” Nintendo, [Online]. Available: https://www.nintendo.co.uk/Wii-U/Wii-U-344102.html. [Accessed 10 May 2019]. [22] HobbyKing, “Turnigy 5000mAh 3S 20C Lipo Pack w/XT-60,” HobbyKing, [Online]. Available: https://hobbyking.com/en_us/turnigy-5000mah-3s-20c-lipo-pack-xt- 90.html?___store=en_us. [Accessed 20 April 2019]. [23] A. Eames, “How Much Power Does Raspberry Pi 3B+ Use? Power Measurements,” 15 March 2018. [Online]. Available: https://raspi.tv/2018/how-much-power-does-raspberry-pi-3b-use- power-measurements. [Accessed 10 May 2019]. [24] RS Components Ltd., “Arcolectric Illuminated Double Pole Single Throw (DPST), Latching Rocker Switch Panel Mount,” RS Components Ltd., [Online]. Available: https://uk.rs- online.com/web/p/rocker-switches/3779759/. [Accessed 9 May 2019]. [25] seapremium, “Buck Car Voltage 5V 9 12V 24V 5A 4-38V to 3.3V Converter Module DC-DC Down Step,” eBay, [Online]. Available: https://www.ebay.co.uk/itm/Buck-Car-Voltage-5V-9-12V- 24V-5A-4-38V-to-3-3V-Converter-Module-DC-DC-Down- Step/254131078582?hash=item3b2b6485b6:g:jO4AAOSwJrpca8HZ&frcectupt=true. [Accessed 22 April 2019]. [26] Raspberry Pi Foundation, “GPIO,” Raspberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/documentation/hardware/raspberrypi/gpio/README.md. [Accessed 9 May 2019]. [27] TOSHIBA, TB6612FNG, TOSHIBA, 2007. [28] CPC - Combined Precision Components, “Stepper Motor, 48 Step, 12V dc - 918,” Premier Farnell, [Online]. Available: https://cpc.farnell.com/adafruit/918/stepper-motor-48-step- 12vdc/dp/MC02059. [Accessed 20 April 2019]. [29] Nexus Automation Limited, “(4 inch)100mm Aluminum Mecanum Wheels Set Basic ( 2 Left, 2 Right) for robot car 14162,” AliExpress, [Online]. Available: https://www.aliexpress.com/item/4-inch-100mm-Aluminum-Mecanum-Wheels-Set-Basic-2- Left-2-Right-for-robot- car/32600253682.html?spm=a2g0s.13010208.99999999.263.12a93c006WOdHz. [Accessed 20 April 2019]. [30] Technobots Ltd., “Zinc Collets 5mm pk/4,” Technobots Ltd., [Online]. Available: https://www.technobotsonline.com/zinc-collets-5mm-pk-4.html. [Accessed 20 April 2019]. [31] Nexus Automation Limited, “10mm hub 18009,” AliExpress, [Online]. Available: https://www.aliexpress.com/item/10mm-Hub- 18009/1922394756.html?spm=a2g0s.13010208.99999999.260.12a93c006WOdHz. [Accessed 20 April 2019]. [32] Rapid Electronics Limited, “Adafruit 2448 TB6612 1.2A DC / Stepper / Solenoid Motor Driver Breakout Board,” Rapid Electronics Limited, [Online]. Available: https://www.rapidonline.com/adafruit-2448-tb6612-1-2a-dc-stepper-solenoid-motor-driver- breakout-board-73-5310. [Accessed 21 April 2019].

29 [33] Raspberry Pi Foundation, “Raspberry Pi 3 Model B+,” Raspberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/. [Accessed 8 May 2019]. [34] Raspberry Pi Foundation, “Setting up a Raspberry Pi as an access point in a standalone network (NAT),” Rapsberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md. [Accessed 8 May 2019]. [35] Raspberry Pi Foundation, “Camera Module v2,” Raspberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/products/camera-module-v2/. [Accessed 8 May 2019]. [36] VANYE, “Dupont Wire for Arduino 120pcs Multicolored VANYE Breadboard Jumper Wires Ribbon Cables Kit 40pin Male to Female 40pin Male to Male 40pin Female to Female,” Amazon.com, Inc., [Online]. Available: https://smile.amazon.co.uk/dp/B07CWSBNYL/ref=pe_3187911_185740111_TE_item. [Accessed 9 May 2019]. [37] R. Santos, “rpi_camera_surveillance_system.py,” GitHub, Inc., 31 October 2017. [Online]. Available: https://github.com/RuiSantosdotme/Random-Nerd- Tutorials/blob/master/Projects/rpi_camera_surveillance_system.py. [Accessed 9 May 2019]. [38] B. Nuttall and D. Jones, “gpiozero,” Read the Docs, 12 February 2019. [Online]. Available: https://gpiozero.readthedocs.io/en/stable/. [Accessed 7 May 2019]. [39] Python Software Foundation, “time - Time access and conversions,” 7 May 2019. [Online]. Available: https://docs.python.org/3/library/time.html. [Accessed 7 May 2019]. [40] Python Software Foundation, “subprocess - Subprocess management,” 7 May 2019. [Online]. Available: https://docs.python.org/3.7/library/subprocess.html. [Accessed 7 May 2019]. [41] P. Howard and @RogueHAL13, “Raspberry Pi Pinout,” 13 April 2019. [Online]. Available: https://pinout.xyz/. [Accessed 10 May 2019]. [42] R. Santos, “Random-Nerd-Tutorials/Projects/rpi_camera_surveillance_system.py,” GitHub, Inc., 31 October 2017. [Online]. Available: https://github.com/RuiSantosdotme/Random-Nerd- Tutorials/blob/master/Projects/rpi_camera_surveillance_system.py. [Accessed 27 April 2019]. [43] Raspberry Pi Foundation, “Raspberry Pi 3 Model A+,” Raspberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/products/raspberry-pi-3-model-a-plus/. [Accessed 8 May 2019]. [44] Raspberry Pi Foundation, “BCM2837B0,” Raspberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2837b0/README.m d. [Accessed 9 May 2019]. [45] PIMORONI LTD., “1200mAh – LiPo Battery Pack,” PIMORONI LTD., [Online]. Available: https://shop.pimoroni.com/products/lipo-battery-pack?variant=20429082183. [Accessed 21 April 2019]. [46] PIMORONI LTD., “PowerBoost 1000 Charger - Rechargeable 5V Lipo USB Boost @ 1A - 1000C,” PIMORONI LTD., [Online]. Available: https://shop.pimoroni.com/products/powerboost-1000- charger-rechargeable-5v-lipo-usb-boost-1a-1000c. [Accessed 21 April 2019]. [47] Adafruit, “Pinouts,” Adafruit, 8 May 2019. [Online]. Available: https://learn.adafruit.com/adafruit-powerboost-1000c-load-share-usb-charge-boost/pinouts. [Accessed 9 May 2019]. [48] PIMORONI LTD., “PiTFT Plus 480x320 3.5" TFT+Touchscreen for Raspberry Pi,” PIMORONI LTD., [Online]. Available: https://shop.pimoroni.com/products/pitft-plus-480x320-3-5-tft- touchscreen-for-raspberry-pi-pi-2-and-model-a-b. [Accessed 7 May 2019].

30 [49] PIMORONI LTD., “12mm - pack of 5 – Tactile Switches,” PIMORONI LTD., [Online]. Available: https://shop.pimoroni.com/products/tactile-switches?variant=372242669. [Accessed 7 May 2019]. [50] PIMORONI LTD., “Yellow - (pack of 10) – Tactile Switch Caps,” PIMORONI LTD., [Online]. Available: https://shop.pimoroni.com/products/colourful-switch-caps?variant=372246987. [Accessed 7 May 2019]. [51] “pigpio Daemon,” 23 March 2019. [Online]. Available: http://abyz.me.uk/rpi/pigpio/pigpiod.html. [Accessed 10 May 2019]. [52] Autodesk Inc., “Fusion 360,” Autodesk Inc., [Online]. Available: https://www.autodesk.co.uk/products/fusion-360/overview. [Accessed 7 May 2019]. [53] McMaster-Carr Supply Company, “Home,” McMaster-Carr Supply Company, [Online]. Available: https://www.mcmaster.com/. [Accessed 8 May 2019]. [54] GrabCAD, “GrabCAD,” stratasys, [Online]. Available: https://grabcad.com/. [Accessed 8 May 2019]. [55] Tiertime, “Box+,” Tiertime, [Online]. Available: https://www.tiertime.com/up-box-plus/. [Accessed 21 April 2019]. [56] Autodesk Inc., “EAGLE,” Autodesk Inc., [Online]. Available: https://www.autodesk.co.uk/products/eagle/overview. [Accessed 7 May 2019]. [57] Haringey Council Services, Building Regulations Part M 2004 Access to and Use of Buildings Designers Checklist of Provisions/Areas for Consideration., Haringey: Haringey Council Services, 2004. [58] Raspberry Pi Foundation, “BCM2835,” Raspberry Pi Foundation, [Online]. Available: https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/README.md. [Accessed 9 May 2019]. [59] CNC Kitchen, “Threaded Inserts in 3D Prints - How strong are they?,” 24 March 2019. [Online]. Available: https://www.youtube.com/watch?v=iR6OBlSzp7I. [Accessed 7 April 2019]. [60] T. Burger, “How Fast is Realtime? Human Perception and Technology,” PubNub Inc., 9 February 2015. [Online]. Available: https://www.pubnub.com/blog/how-fast-is-realtime-human- perception-and-technology/. [Accessed 30 July 2018]. [61] ISS Multilateral Control Board, International Docking System Standard (IDSS) Interface Definition Document (IDD) Revision E, 2016. [62] A. Witze, “Software error doomed Japanese Hitomi spacecraft,” Macmillan Publishers Limited, 28 April 2016. [Online]. Available: https://www.nature.com/news/software-error-doomed- japanese-hitomi-spacecraft-1.19835. [Accessed 30 July 2018]. [63] Concrete Construction Staff, “Recommended Floor Slope and Tolerance,” Hanley Wood Media, Inc, 1 February 1998. [Online]. Available: https://www.concreteconstruction.net/how- to/recommended-floor-slope-and-tolerance_o. [Accessed 29 July 2018]. [64] Jamie, “Syntax Highlight Code In Word Documents,” [Online]. Available: http://www.planetb.ca/syntax-highlight-word. [Accessed 5 May 2019]. [65] Tyler, “How to add a power button to your Raspberry Pi,” howchoo, llc, [Online]. Available: https://howchoo.com/g/mwnlytk3zmm/how-to-add-a-power-button-to-your-raspberry-pi. [Accessed 22 April 2019]. [66] World Health Organisation, “Health effects of UV radiation,” World Health Organisation, [Online]. Available: https://www.who.int/uv/health/uv_health2/en/. [Accessed 9 May 2019].

31 Appendix A – Requirements Specification A.1 Mechanical Requirements MEC-0010 Dimensions The system excluding payload shall have a length no more than 40 cm, a width no more than 30 cm and a height no more than 30 cm.

MEC-0020 Mass The system shall have a total mass of no more than 10 kg.

A.2 Electrical Requirements ELE-0010 Battery capacity The system shall be driven by a battery with a capacity of no more than 5 Ah.

ELE-0020 Battery voltage The battery shall have a nominal voltage of no more than 12 V.

A.3 Control Requirements CON-0010 Manual control The control system shall provide fully manual control over all robot motion.

CON-0020 Freedom The control system shall provide full rotational and translational control across the plane upon which the robot operates.

CON-0030 Emergency stop The control system shall provide a button or other mechanism to cut all power to the robot in the event of an emergency.

CON-0040 Conservation of speed The system shall simulate Newton’s First Law as applying without resistance from the ground or air, as these resistances would not apply in space.

CON-0050 Latency The control system shall have a latency of no more than 100 ms [60].

CON-0060 Vision The robot shall include a forward-facing camera to allow the user to view the robot’s trajectory.

CON-0070 Controller range The controller shall be capable of commanding the robot and viewing its live video feed from a distance of 5 m.

A.4 Propulsion Requirements PRO-0010 Translation speed The robot shall provide a maximum translation speed of at least 30 cm/s. This is based on three times the maximum for the International Docking System Standard (IDSS) [61]. This gives a large margin to simulate non-nominal docking situations.

32 PRO-0020 Rotation speed The robot shall provide a maximum rotation speed of at least 70 deg/s. This is based on the spin rate of the failed Hitomi satellite, measured from the ground as one revolution every 5.2 seconds [62].

PRO-0030 Linear acceleration The robot shall provide a minimum linear acceleration of 10 cm/s. This is based on taking 2.5 s to reach the maximum translation speed.

PRO-0040 Angular acceleration The robot shall provide a minimum angular acceleration of 28 deg/s. This is based on taking 2.5 s to reach the maximum rotation speed.

A.5 Operation Requirements OPS-0010 Battery life The system shall have a battery life of at least 60 minutes.

OPS-0020 Slope The robot shall provide full speed motion on a surface with a slope of up to 2 % [63].

A.6 Interface Requirements INT-0010 Wireless connectivity The system shall provide for wireless updates of onboard software.

INT-0020 Manual control interface Any manual control of the robot shall be across a wireless link.

A.7 Safety Requirements SAF-0010 Robot overcurrent cut-off The robot shall include an automatic method of totally electrically isolating the battery from the rest of the robot if the total current drawn exceeds 5 A.

SAF-0020 Controller overcurrent cut-off The controller shall include an automatic method of totally electrically isolating the battery from the rest of the controller if the total current drawn exceeds 3 A.

33 Appendix B - Robot Code All code in this Appendix and Appendix C - Controller Code was formatted using the PlanetB syntax highlighting page [64].

B.1 Motion Code

1. # Code for the robot of the CubeSat Docking Simulator (CDS) Final Year Project (FYP ) 2. # Copyright William Easdown 2019, all rights reserved 3. 4. ################################################################################### ######################## 5. ## Function definitions 6. 7. def motor_speeds(motor1_speed, motor2_speed, motor3_speed, motor4_speed, dms): 8. """Function to set the motor speeds based on controller button presses""" 9. if btntl.is_pressed: 10. if (motor1_speed <= 100 and motor1_speed > -100): 11. motor1_speed -= dms 12. if motor2_speed < 100: 13. motor2_speed += dms 14. if motor3_speed < 100: 15. motor3_speed += dms 16. if (motor4_speed <= 100 and motor4_speed > -100): 17. motor4_speed -= dms 18. 19. if btntr.is_pressed: 20. if motor1_speed < 100: 21. motor1_speed += dms 22. if (motor2_speed <= 100 and motor2_speed > -100): 23. motor2_speed -= dms 24. if (motor3_speed <= 100 and motor3_speed > -100): 25. motor3_speed -= dms 26. if motor4_speed < 100: 27. motor4_speed += dms 28. 29. if btntf.is_pressed: 30. if motor1_speed < 100: 31. motor1_speed += dms 32. if motor2_speed < 100: 33. motor2_speed += dms 34. if motor3_speed < 100: 35. motor3_speed += dms 36. if motor4_speed < 100: 37. motor4_speed += dms 38. 39. if btntb.is_pressed: 40. if (motor1_speed <= 100 and motor1_speed > -100): 41. motor1_speed -= dms 42. if (motor2_speed <= 100 and motor2_speed > -100): 43. motor2_speed -= dms 44. if (motor3_speed <= 100 and motor3_speed > -100): 45. motor3_speed -= dms 46. if (motor4_speed <= 100 and motor4_speed > -100): 47. motor4_speed -= dms 48. 49. if btnrl.is_pressed: 50. if (motor1_speed <= 100 and motor1_speed > -100): 51. motor1_speed -= dms 52. if (motor2_speed <= 100 and motor2_speed > -100): 53. motor2_speed -= dms 54. if motor3_speed < 100: 55. motor3_speed += dms

34 56. if motor4_speed < 100: 57. motor4_speed += dms 58. 59. if btnrr.is_pressed: 60. if motor1_speed < 100: 61. motor1_speed += dms 62. if motor2_speed < 100: 63. motor2_speed += dms 64. if (motor3_speed <= 100 and motor3_speed > -100): 65. motor3_speed -= dms 66. if (motor4_speed <= 100 and motor4_speed > -100): 67. motor4_speed -= dms 68. 69. return [motor1_speed, motor2_speed, motor3_speed, motor4_speed]; 70. 71. def pulse(xPin): 72. xPin.on() 73. sleep(0.00003) 74. xPin.off() 75. return; 76. 77. def stop(allpins): 78. """Function to halt the motors""" 79. if btnoff.is_pressed: 80. print("button off pressed") 81. speeds = [0,0,0,0] 82. for i in range(4): # Iterate through each pin of each wheel and turn it off

83. for pin in allpins[i]: 84. pin.off() 85. return speeds; 86. return; 87. 88. def shutdown(allpins): 89. """Function to shutdown the robot if the stop button is held for three seconds. The controller shutdown is handled locally on the controller.""" 90. if btnoff.is_held: 91. stop(allpins) 92. standby.on() # Disable the motor controllers 93. call(['shutdown', '-h', 'now'], shell=False) 94. 95. return; 96. 97. def stepper_drive(allpins, speeds): 98. # Code derived from https://www.hackster.io/mjrobot/playing-with-electronics- rpi-gpio-zero-library-tutorial-f984c9 99. mode = 0 # mode = 1: Low Speed ==> Higher Power 100. # mode = 0: High Speed ==> Lower Power 101. if mode: # Low Speed ==> High Power 102. seq = [[1,0,0,1], # Define step sequence as shown in manufacturers dat asheet 103. [1,0,0,0], 104. [1,1,0,0], 105. [0,1,0,0], 106. [0,1,1,0], 107. [0,0,1,0], 108. [0,0,1,1], 109. [0,0,0,1]] 110. else: # High Speed ==> Low Power 111. seq = [[1,0,0,0], # Define step sequence as shown in manufacturers da tasheet 112. [0,1,0,0], 113. [0,0,1,0], 114. [0,0,0,1]] 115. stepCount = len(seq) 116. stepCounter = [0,0,0,0] # A counter for each wheel

35 117. stepDir = 0 # Initialise the step direction variable 118. waitTime = [0,0,0,0] # Initialise the waitTime list 119. 120. while True: # Start main loop 121. print("speeds before stop()", speeds) 122. stop(allpins) 123. shutdown(allpins) 124. speeds = motor_speeds(speeds[0], speeds[1], speeds[2], speeds[3], dm s) 125. 126. #print(speeds) 127. for wheel in range(4): # Iterate through the wheels 128. 129. if ((wheel == 0) or (wheel == 1)): # if it's a left wheel: 130. if speeds[wheel] > 0: # if the speed on this wheel is greate r than 0 131. stepDir = - 1 # Positive speed is anticlockwise rotation 132. waitTime[wheel] = (- 1.6*speeds[wheel]+162)/10000 # Set the waitTime on this wheel according to the form ula 133. if speeds[wheel] <= 0: 134. stepDir = 1 135. waitTime[wheel] = (-1.6*speeds[wheel]+162)/10000 136. 137. if ((wheel == 2) or (wheel == 3)): # if it's a right wheel 138. if speeds[wheel] > 0: 139. stepDir = 1 # Positive speed is clockwise rotation 140. waitTime[wheel] = (-1.6*speeds[wheel]+162)/10000 141. if speeds[wheel] <= 0: 142. stepDir = -1 143. waitTime[wheel] = (-1.6*speeds[wheel]+162)/10000 144. 145. for fpin in range(4): # for each pin corresponding to the wheel in question 146. xPin=allpins[wheel][fpin] # Give it a temporary name 147. if seq[stepCounter[wheel]][fpin]!=0: # if the sequence defin ed above is not 0 148. pulse(xPin) 149. else: 150. xPin.off() 151. 152. stepCounter[wheel] += stepDir # The stepCounter for this wheel i ncreases/decreases 153. if (stepCounter[wheel] >= stepCount): 154. stepCounter[wheel] = 0 # Reset StepCounter if at the end of the sequence 155. if (stepCounter[wheel] < 0): 156. stepCounter[wheel] = stepCount+stepDir # Reset stepCounter i f moving in reverse and hit beginning 157. sleep(waitTime[wheel]) # Wait before moving on 158. print("Wait time =", waitTime) 159. return; 160. 161. ############################################################################ ############################### 162. ### Setup 163. 164. ## Import necessary libraries and components 165. # Import gpiozero components 166. from gpiozero import Button 167. from gpiozero.pins.pigpio import PiGPIOFactory 168. from gpiozero import OutputDevice 169. 170. # Import sleep function for stepper_drive() 171. from time import sleep

36 172. 173. # Import call function for shutdown() 174. from subprocess import call 175. 176. # Establish motor speed variables 177. motor1_speed = 0 178. motor2_speed = 0 179. motor3_speed = 0 180. motor4_speed = 0 181. speeds = [motor1_speed, motor2_speed, motor3_speed, motor4_speed] 182. dms = 10 # % change in motor speed per thruster firing 183. 184. # Motor pins: 1 = Ain1, 2 = Ain2, 3 = Bin1, 4 = Bin2 185. # Pins for motor 1 186. S11 = OutputDevice(18) 187. S12 = OutputDevice(17) 188. S13 = OutputDevice(27) 189. S14 = OutputDevice(4) 190. step1Pins = [S11,S12,S13,S14] 191. 192. # Pins for motor 2 193. S21 = OutputDevice(23) 194. S22 = OutputDevice(22) 195. S23 = OutputDevice(24) 196. S24 = OutputDevice(25) 197. step2Pins = [S21,S22,S23,S24] 198. 199. # Pins for motor 3 200. S31 = OutputDevice(6) 201. S32 = OutputDevice(5) 202. S33 = OutputDevice(13) 203. S34 = OutputDevice(12) 204. step3Pins = [S31,S32,S33,S34] 205. 206. # Pins for motor 4 207. S41 = OutputDevice(20) 208. S42 = OutputDevice(26) 209. S43 = OutputDevice(19) 210. S44 = OutputDevice(16) 211. step4Pins = [S41,S42,S43,S44] 212. 213. allpins = [step1Pins, step2Pins, step3Pins, step4Pins] 214. 215. # Initialise standby pin 216. standby = OutputDevice(21, False) 217. 218. # Initialise controller buttons 219. factory = PiGPIOFactory('192.168.4.9') # IP address of controller 220. 221. btnoff = Button(27, pin_factory = factory, bounce_time = 0.2, hold_time = 3) # remote shutdown button 222. 223. btntl = Button(6, pin_factory = factory, bounce_time = 0.2) # remote transla te left button 224. btntr = Button(26, pin_factory = factory, bounce_time = 0.2) # remote transl ate right button 225. btntf = Button(13, pin_factory = factory, bounce_time = 0.2) # remote transl ate forwards button 226. btntb = Button(19, pin_factory = factory, bounce_time = 0.2) # remote transl ate backwards button 227. 228. btnrl = Button(17, pin_factory = factory, bounce_time = 0.2) # remote rotate anti-clockwise button 229. btnrr = Button(18, pin_factory = factory, bounce_time = 0.2) # remote rotate clockwise button 230.

37 231. ############################################################################ ############################### 232. ## Loop 233. stepper_drive(allpins, speeds)

B.2 Camera Code

1. # Web streaming example 2. # Source code from the official PiCamera package 3. # http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming 4. # This code copied from https://github.com/RuiSantosdotme/Random-Nerd- Tutorials/blob/master/Projects/rpi_camera_surveillance_system.py 5. # View stream at http://your-pi-address:8000/ 6. 7. import io 8. import picamera 9. import logging 10. import socketserver 11. from threading import Condition 12. from http import server 13. 14. PAGE="""\ 15. 16. 17. Raspberry Pi - Surveillance Camera 18. 19. 20.

Mecanum Docking Simulator Livestream

21.
22. 23. 24. """ 25. 26. class StreamingOutput(object): 27. def __init__(self): 28. self.frame = None 29. self.buffer = io.BytesIO() 30. self.condition = Condition() 31. 32. def write(self, buf): 33. if buf.startswith(b'\xff\xd8'): 34. # New frame, copy the existing buffer's content and notify all 35. # clients it's available 36. self.buffer.truncate() 37. with self.condition: 38. self.frame = self.buffer.getvalue() 39. self.condition.notify_all() 40. self.buffer.seek(0) 41. return self.buffer.write(buf) 42. 43. class StreamingHandler(server.BaseHTTPRequestHandler): 44. def do_GET(self): 45. if self.path == '/': 46. self.send_response(301) 47. self.send_header('Location', '/index.html') 48. self.end_headers() 49. elif self.path == '/index.html': 50. content = PAGE.encode('utf-8') 51. self.send_response(200) 52. self.send_header('Content-Type', 'text/html') 53. self.send_header('Content-Length', len(content)) 54. self.end_headers()

38 55. self.wfile.write(content) 56. elif self.path == '/stream.mjpg': 57. self.send_response(200) 58. self.send_header('Age', 0) 59. self.send_header('Cache-Control', 'no-cache, private') 60. self.send_header('Pragma', 'no-cache') 61. self.send_header('Content-Type', 'multipart/x-mixed- replace; boundary=FRAME') 62. self.end_headers() 63. try: 64. while True: 65. with output.condition: 66. output.condition.wait() 67. frame = output.frame 68. self.wfile.write(b'--FRAME\r\n') 69. self.send_header('Content-Type', 'image/jpeg') 70. self.send_header('Content-Length', len(frame)) 71. self.end_headers() 72. self.wfile.write(frame) 73. self.wfile.write(b'\r\n') 74. except Exception as e: 75. logging.warning( 76. 'Removed streaming client %s: %s', 77. self.client_address, str(e)) 78. else: 79. self.send_error(404) 80. self.end_headers() 81. 82. class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer): 83. allow_reuse_address = True 84. daemon_threads = True 85. 86. with picamera.PiCamera(resolution='640x480', framerate=24) as camera: 87. output = StreamingOutput() 88. #Uncomment the next line to change your Pi's Camera rotation (in degrees) 89. camera.rotation = 180 90. camera.start_recording(output, format='mjpeg') 91. try: 92. address = ('', 8000) 93. server = StreamingServer(address, StreamingHandler) 94. server.serve_forever() 95. finally: 96. camera.stop_recording()

39 Appendix C - Controller Code C.1 Shutdown Python File The Python file used to shut down the controller Raspberry Pi was derived from an article by user Tyler on howchoo [65]. It was edited to use the gpiozero library instead of the RPi.GPIO library used in the original to match the usage of gpiozero in the main robot code and due to this author’s greater familiarity with gpiozero over RPi.GPIO.

1. #!/usr/bin/env python 2. 3. # Program to shutdown controller when stop/shutdown button held for five seconds 4. # Derived from https://howchoo.com/g/mwnlytk3zmm/how-to-add-a-power-button-to-your- raspberry-pi 5. # Updated to use gpiozero library rather than RPi.GPIO to match robot_main. 6. 7. from gpiozero import Button 8. from gpiozero.pins.pigpio import PiGPIOFactory 9. import subprocess 10. 11. shutdown = Button(pin=5, bounce_time=0.2, hold_time=5) 12. shutdown.wait_for_release() 13. 14. subprocess.call(['shutdown', '-h', 'now'], shell=False)

C.2 Shutdown Shell Script The Python file in Shutdown Python File must be added to a script file to be run on boot [65]. This script file was copied from same article as the shutdown Python file in Appendix C.1 - Shutdown Python File.

1. #! /bin/sh 2. 3. ### BEGIN INIT INFO 4. # Provides: shutdown_button.py 5. # Required-Start: $remote_fs $syslog 6. # Required-Stop: $remote_fs $syslog 7. # Default-Start: 2 3 4 5 8. # Default-Stop: 0 1 6 9. ### END INIT INFO 10. 11. # Copied from https://howchoo.com/g/mwnlytk3zmm/how-to-add-a-power-button-to-your- raspberry-pi 12. 13. # If you want a command to always run, put it here 14. 15. # Carry out specific functions when asked to by the system 16. case "$1" in 17. start) 18. echo "Starting shutdown_button.py" 19. /usr/local/bin/shutdown_button.py & 20. ;; 21. stop) 22. echo "Stopping shutdown_button.py" 23. pkill -f /usr/local/bin/shutdown_button.py 24. ;; 25. *) 26. echo "Usage: /etc/init.d/shutdown_button.sh {start|stop}" 27. exit 1 28. ;; 29. esac 30. 31. exit 0

40 Appendix D – Mechanical Drawings D.1 Robot Chassis

Figure 19 - Robot chassis mechanical drawing 41

Appendix E – Bills of Materials E.1 Robot Table 3 - Robot BOM

MDS BoM - Robot Category Item no. Description Supplier Part no. Quantity Cost per unit Cost Shipping Total Purchased Link Chassis CH-001 ABS junction box Amazon - 1 £20.21 £20.21 £2.00 £22.21 Y https://smile.amazon.co.uk/Rectangle-Waterproof-Electric-Junction-263x182x125mm/dp/B01EZP4DKI/ref=smi_www_rco2_go_smi_8682124849?_encoding=UTF8&%2AVersion%2A=1&%2Aentries%2A=0&ie=UTF8 CH-002 Rocker switch RS 377-9759 1 £3.49 £3.49 £0.00 £3.49 Y https://uk.rs-online.com/web/p/rocker-switches/3779759/

Propulsion P-001 Stepper motor CPC MC02059 4 £7.21 £28.84 £0.00 £28.84 Y https://cpc.farnell.com/adafruit/918/stepper-motor-48-step-12vdc/dp/MC02059 P-002 Stepper controller Rapid 73-5310 4 £5.58 £22.32 £3.59 £25.91 Y https://www.rapidonline.com/adafruit-2448-tb6612-1-2a-dc-stepper-solenoid-motor-driver-breakout-board-73-5310 P-003 100mm Mecanum wheel set AliExpress - 1 £67.78 £67.78 £69.30 £137.08 Y https://www.aliexpress.com/item/4-inch-100mm-Aluminum-Mecanum-Wheels-Set-Basic-2-Left-2-Right-for-robot-car/32600253682.html?spm=a2g0s.13010208.99999999.263.12a93c006WOdHz P-004 10mm hubs AliExpress - 4 £7.97 £31.88 £20.95 £52.83 Y https://www.aliexpress.com/item/10mm-Hub-18009/1922394756.html?spm=a2g0s.13010208.99999999.260.12a93c006WOdHz P-005 5mm zinc collets 4pk Technobots 4609-050 1 £2.04 £2.04 £2.46 £4.50 Y https://www.technobotsonline.com/zinc-collets-5mm-pk-4.html

Control RC-001 Raspberry Pi 3 Model B+ Stock - 1 £0.00 £0.00 £0.00 £0.00 Y - RC-002 Raspberry Pi Camera Module Stock - 1 £0.00 £0.00 £0.00 £0.00 Y - RC-003 Pi Camera cable The Pi Hut N/A 1 £2.00 £2.00 £2.99 £4.99 Y https://thepihut.com/products/adafruit-flex-cable-for-raspberry-pi-camera-300mm-12

Power PO-001 5000mAh Turnigy 3S 20C battery pack HobbyKing 9067000276-0 1 £19.12 £19.12 £5.98 £25.10 Y https://hobbyking.com/en_us/turnigy-5000mah-3s-20c-lipo-pack-xt-90.html PO-002 Turnigy 12 V Basic Balance Charger HobbyKing Turnigy-3S 1 £4.17 £4.17 - £4.17 Y https://hobbyking.com/en_us/turnigy-12v-2-3s-basic-balance-charger.html PO-003 Male XT60 connectors 5pk Amazon - 1 £6.99 £6.99 £0.00 £6.99 Y https://smile.amazon.co.uk/FancyWhoop-Connector-Housing-Silicon-Battery/dp/B073QMJMRV/ PO-004 12V to 5V 5A Buck converter eBay N/A 1 £1.62 £1.62 £0.69 £2.31 Y https://www.ebay.co.uk/itm/Buck-Car-Voltage-5V-9-12V-24V-5A-4-38V-to-3-3V-Converter-Module-DC-DC-Down-Step/254131078582?hash=item3b2b6485b6:g:jO4AAOSwJrpca8HZ&frcectupt=true

Fixings FI-001 M5x60mm screws stainless steel 50pk RS 914-1605 1 £19.18 £19.18 £0.00 £19.18 Y https://uk.rs-online.com/web/p/products/9141605/ FI-002 Standoffs Stock - 4 £0.00 £0.00 £0.00 £0.00 Y FI-003 Female/female jumper wires 30cm 40pk Amazon - 1 £5.69 £5.69 £0.00 £5.69 Y https://smile.amazon.co.uk/dp/B07CWSBNYL/ref=pe_3187911_185740111_TE_item

Total £235.33 Shipping Total £107.96 Grand Total £343.29

42 E.2 Controller Table 4 - Controller BOM

MDS BoM - Controller Item no. Description Supplier Part no. Quantity Cost per unit Cost Shipping Purchased Date purchased Order no. Link CO-001 3D printed case University - 1 £25.00 £25.00 £0.00 Y CO-002 Tactile switches 12mm x5 Pimoroni COM0403 2 £2.00 £4.00 £7.00 Y 18/09/2018 #PI281082 https://shop.pimoroni.com/products/tactile-switches?variant=372242669 CO-003 Tactile switch caps yellow x10 Pimoroni COM0703 1 £1.50 £1.50 - Y 18/09/2018 #PI281082 https://shop.pimoroni.com/products/colourful-switch-caps?variant=372246987 CO-004 Raspberry Pi 3A+ CPC SC14977 1 £26.75 £26.75 £0.00 Y https://cpc.farnell.com/raspberry-pi/rpi3-modap/sbc-raspberry-pi-3-model-a-512mb/dp/SC14977 CO-005 LiPo battery pack 1200mAh Pimoroni BAT0004 1 £7.00 £7.00 - Y 18/09/2018 #PI281082 https://shop.pimoroni.com/products/lipo-battery-pack?variant=20429082183 CO-006 PowerBoost 1000 Charger Pimoroni ADA2465 1 £17.70 £17.70 - Y 18/09/2018 #PI281082 https://shop.pimoroni.com/products/powerboost-1000-charger-rechargeable-5v-lipo-usb-boost-1a-1000c CO-007 Adafruit PiTFT Plus 480x320 3.5" touchscreen Pimoroni ADA2441 1 £41.40 £41.40 £0.00 Y https://shop.pimoroni.com/products/pitft-plus-480x320-3-5-tft-touchscreen-for-raspberry-pi-pi-2-and-model-a-b CO-008 Micro USB cable 6 inches Amazon - 1 £2.39 £2.39 - Y 05/03/2019 204-4747598-2099511 https://smile.amazon.co.uk/gp/product/B003YKX6WM/ref=ppx_od_dt_b_asin_title_s00?ie=UTF8&psc=1 CO-009 PCB manufacture Stock - 1 £0.00 £0.00 £0.00 Y CO-010 Rocker switch 5pk Stock - 1 £0.00 £0.00 £0.00 Y https://uk.rs-online.com/web/p/rocker-switches/0419750/ CO-011 M3 self-tapping screws Stock - 1 £0.00 £0.00 £0.00 Y https://uk.rs-online.com/web/p/self-tapping-screws/5005101/

Total £125.74 Shipping Total £7.00 Grand Total £132.74

43 Appendix F – PCB Manufacture Process To manufacture the controller button PCBs, the photoresist method was used. The process is described in detail below.

F.1 Preparation A positive image of the track layout was printed on a piece of paper for checking of tracks, particularly to ensure sufficient spacing between signals. The layout was then printed in black on a projector transparency sheet. A photo etch-resist board was cut to the size of the boards with a 1 mm margin on every side. Eye goggles were worn to protect against any flying shards, as well as a dust mask to prevent ingestion of dust from the FR-4 fibreglass substrate.

Figure 20 - Copper layout printed on a projector transparency sheet.

F.2 Exposure An ultraviolet (UV) light box in a darkened room was used to expose the board. The board was laid on top of the transparency, covered to ensure no harmful UV could escape, then exposed for five minutes. The areas of board not covered by the black on the transparency were exposed to the UV. This meant these areas would become possible to etch after development.

F.3 Development As soon as the exposure was finished, the board was submerged in a sodium hydroxide (NaOH) developer solution. The board was agitated in the solution to ensure even coverage and to speed up development. Development took approximately three minutes.

The development process caused the exposed areas on the board are washed away, leaving bare copper, as shown in Figure 21. According to the manufacturer’s datasheet, the developer should be at approximately 20°C for the best results. The areas not exposed, corresponding to the tracks and ground plane, remain on the copper and are resistant to the following etching process. After development, the board was rinsed thoroughly to avoid a chemical reaction between the development and etching chemicals.

44

Figure 21 - A board after development.

F.4 Etching Once development was complete, the board needed to be etched to do some stuff. Ferric chloride (FeCl3) solution was used and was pre-heated, so it was warm to the touch for best results. The process etched away the photoresist, leaving the copper traces and ground plane. Etching lasts 10-20 minutes depending on the age of the etchant. In this case, fresh etchant was used.

After etching the board was rinsed thoroughly to avoid excess etching.

F.5 Clean up After etching, the board was cut in half to form the two boards that would be used in the controller. Holes were drilled in the boards, so the buttons could be attached and the boards mounted to the controller case. Finally, a silicon carbide cleaning powder (Vim) was used to remove the remaining etch resist, leaving the completed unpopulated PCB, as shown in Figure 22.

Figure 22 - The completed boards after drilling and clean up.

45 F.6 Safety During the PCB manufacture process, several safety precautions were taken. UV light is dangerous to the skin or eyes [66], so during the exposure process the light box was covered to avoid exposure of the body. During development, latex gloves and goggles were worn to avoid the irritant sodium hydroxide solution coming into contact with the skin or eyes. The etchant solution is a strong irritant and stains, so latex gloves and goggles were again worn, along with an apron.

46 Appendix G – Setting Buck Converter Output Voltage When the buck converter used to power the robot arrived, its potentiometer was set such that its output voltage was the same as its input voltage. This needed to be adjusted so that the output was at 5 V. It was also necessary for this output to remain fixed to avoid damaging the Raspberry Pi or motor controllers, so the potentiometer on the buck converter needed replacing with a fixed value resistor.

Initially, the potentiometer was set so the output voltage was 5.15 V. It was then desoldered and its resistance measured, giving a value of 5.7 kΩ. A 5.6 kΩ 1206 package SMD resistor was soldered in its place and the output voltage from the buck converter was measured as 5.04 V. This was felt too low to accommodate any voltage drop in the supply wires. A 6.2 kΩ resistor was next tried, giving an output voltage of 5.49 V – this was outside of the specification of devices driven by 5 V, which can tolerate up to 5.25 V. Finally, a 75 kΩ resistor was soldered in parallel with the 6.2 kΩ, giving a satisfactory output voltage of 5.16 V.

47