66
IN DEGREE PROJECT MECHANICAL ENGINEERING, FIRST CYCLE, 15 CREDITS , STOCKHOLM SWEDEN 2019 Sharkbait - a self-stabilising underwater drone Sharkbait - en självstabiliserande undervattensdrönare Evalution of response time, propulsion and steering in a underwater environment VICTOR HANEFORS SHAYA RAHMANIAN KTH ROYAL INSTITUTE OF TECHNOLOGY SCHOOL OF INDUSTRIAL ENGINEERING AND MANAGEMENT

Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

  • Upload
    others

  • View
    1

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

IN DEGREE PROJECT MECHANICAL ENGINEERINGFIRST CYCLE 15 CREDITS

STOCKHOLM SWEDEN 2019

Sharkbait - a self-stabilising underwater drone Sharkbait - en sjaumllvstabiliserande undervattensdroumlnare

Evalution of response time propulsion and steering in a underwater environment

VICTOR HANEFORS

SHAYA RAHMANIAN

KTH ROYAL INSTITUTE OF TECHNOLOGYSCHOOL OF INDUSTRIAL ENGINEERING AND MANAGEMENT

Sharkbait - A self-stabilising underwater drone

Evalution of response time propulsion and steering in a underwater environment

SHAYA RAHMANIANVICTOR HANEFORS

Bachelorrsquos Thesis at ITMSupervisor Nihad SubasicExaminer Nihad Subasic

TRITA-ITM-EX 201959

Abstract

This projects purpose was to build an underwater re-mote operated vehicle with software controlled self-stabilisationfor evaluation of the response time propulsion and steeringto see what could be achieved A prototype was constructedand tested in dry conditions at first The prototype featuresan Arduino and a Raspberry Pi as control units controllingsix thrusters With the help of a controller the user canmanoeuvre the vehicle and when exposed to unexpectedforces sensors detect this allowing the software to counter-act it Due to risk of massive electrical failure as a resultof failed waterproofing tests underwater were postponeduntil the end Unfortunately this made full optimisationof the software difficult The results in a dry enviromentwere positive the system was able to fully perform the de-sired outputs at the thrusters the PID controller kickedin when it detected a disturbance in its position Testingthe propulsion system in the water gave positive results aswell the propeller held and the motor kept working whilesubmerged The response time performed adequately at anaverage of 50ms

KeywordsMechatronics Drone Underwater Self-stabilisation

ReferatDetta projektets syfte var att bygga en fjarrstyrd undervat-tensdronare med mjukvarustyrd sjalstabilisering for utvarderingav responstid framdrivningen och styrningen for att sevad som gar att uppna En prototyp byggdes och testa-des forst i torra forhallanden Prototypen har kontrollerasmed en Arduino och en Raspberry Pi som styr sex drivmo-torer Genom en kontroller kan anvandare styra farkostenoch om den utsatts for ovantade krafter kan mjukvaranmotverka dom Pa grund av risken for massivt elhaveri omvattentatningen inte ar tillracklig skots tester i vatten uppTyvarr gjorde detta att fullstandig optimering av mjuk-varan blev svar Resultaten i torr miljo var positiv syst-met utforde sin onskade funktion vid motorerna och PIDkontrollern forsokte stalla om positionen till ratta nar denmarkte av en felaktig position Propulsion systemet testa-des i vatten och gav positiva resultat ocksa propellern holloch motoren fortsatte fungera fastan sankt i vatten Re-sponstiden gav ett adekvat utfall pa ungefar 50 ms

NyckelordMekatronik Dronare Undervatten Sjalvstabiliserande

Acknowledgements

We would like to thank the teacher assistants who always helped and gave advicein the workshop as well as always spreading a positive vibe Our supervisor NihadSubasic for his feedback and guidance as well as the fellow students of the MF133Xcourse for valuable feedback on this report and the project in whole Special thanksto Hakan Gerner for his help and suggestions regarding the electrical componentsand configuration of the control units A special thanks aswell to Rouzbeh Delaverfor helping us figure out the small details in our codes which usually makes orbreaks the whole thing

Contents

1 Introduction 111 Project description 112 Inspiration 113 Development potential 214 Scope 2

2 Theory 321 Design 322 Mechanical forces 3

221 Buoyancy Force 4222 Thruster Forces 4

23 Control system 6231 Proportional-Integral-Derivative controller 6

3 Demonstrator 731 Design 732 Components 8

321 Chassis 8322 Thrusters 8323 Inertial Measurement Unit 9324 Control unit 10325 Camera module 11326 USB-controller 11

33 Electrical Circuit 12331 Waterproofing 13

34 Programming solutions 13341 Steering 14342 Controller implementation 15

35 Mechanics 15

4 Result 1741 Propulsion 1742 Steering 18

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 2: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Sharkbait - A self-stabilising underwater drone

Evalution of response time propulsion and steering in a underwater environment

SHAYA RAHMANIANVICTOR HANEFORS

Bachelorrsquos Thesis at ITMSupervisor Nihad SubasicExaminer Nihad Subasic

TRITA-ITM-EX 201959

Abstract

This projects purpose was to build an underwater re-mote operated vehicle with software controlled self-stabilisationfor evaluation of the response time propulsion and steeringto see what could be achieved A prototype was constructedand tested in dry conditions at first The prototype featuresan Arduino and a Raspberry Pi as control units controllingsix thrusters With the help of a controller the user canmanoeuvre the vehicle and when exposed to unexpectedforces sensors detect this allowing the software to counter-act it Due to risk of massive electrical failure as a resultof failed waterproofing tests underwater were postponeduntil the end Unfortunately this made full optimisationof the software difficult The results in a dry enviromentwere positive the system was able to fully perform the de-sired outputs at the thrusters the PID controller kickedin when it detected a disturbance in its position Testingthe propulsion system in the water gave positive results aswell the propeller held and the motor kept working whilesubmerged The response time performed adequately at anaverage of 50ms

KeywordsMechatronics Drone Underwater Self-stabilisation

ReferatDetta projektets syfte var att bygga en fjarrstyrd undervat-tensdronare med mjukvarustyrd sjalstabilisering for utvarderingav responstid framdrivningen och styrningen for att sevad som gar att uppna En prototyp byggdes och testa-des forst i torra forhallanden Prototypen har kontrollerasmed en Arduino och en Raspberry Pi som styr sex drivmo-torer Genom en kontroller kan anvandare styra farkostenoch om den utsatts for ovantade krafter kan mjukvaranmotverka dom Pa grund av risken for massivt elhaveri omvattentatningen inte ar tillracklig skots tester i vatten uppTyvarr gjorde detta att fullstandig optimering av mjuk-varan blev svar Resultaten i torr miljo var positiv syst-met utforde sin onskade funktion vid motorerna och PIDkontrollern forsokte stalla om positionen till ratta nar denmarkte av en felaktig position Propulsion systemet testa-des i vatten och gav positiva resultat ocksa propellern holloch motoren fortsatte fungera fastan sankt i vatten Re-sponstiden gav ett adekvat utfall pa ungefar 50 ms

NyckelordMekatronik Dronare Undervatten Sjalvstabiliserande

Acknowledgements

We would like to thank the teacher assistants who always helped and gave advicein the workshop as well as always spreading a positive vibe Our supervisor NihadSubasic for his feedback and guidance as well as the fellow students of the MF133Xcourse for valuable feedback on this report and the project in whole Special thanksto Hakan Gerner for his help and suggestions regarding the electrical componentsand configuration of the control units A special thanks aswell to Rouzbeh Delaverfor helping us figure out the small details in our codes which usually makes orbreaks the whole thing

Contents

1 Introduction 111 Project description 112 Inspiration 113 Development potential 214 Scope 2

2 Theory 321 Design 322 Mechanical forces 3

221 Buoyancy Force 4222 Thruster Forces 4

23 Control system 6231 Proportional-Integral-Derivative controller 6

3 Demonstrator 731 Design 732 Components 8

321 Chassis 8322 Thrusters 8323 Inertial Measurement Unit 9324 Control unit 10325 Camera module 11326 USB-controller 11

33 Electrical Circuit 12331 Waterproofing 13

34 Programming solutions 13341 Steering 14342 Controller implementation 15

35 Mechanics 15

4 Result 1741 Propulsion 1742 Steering 18

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 3: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Abstract

This projects purpose was to build an underwater re-mote operated vehicle with software controlled self-stabilisationfor evaluation of the response time propulsion and steeringto see what could be achieved A prototype was constructedand tested in dry conditions at first The prototype featuresan Arduino and a Raspberry Pi as control units controllingsix thrusters With the help of a controller the user canmanoeuvre the vehicle and when exposed to unexpectedforces sensors detect this allowing the software to counter-act it Due to risk of massive electrical failure as a resultof failed waterproofing tests underwater were postponeduntil the end Unfortunately this made full optimisationof the software difficult The results in a dry enviromentwere positive the system was able to fully perform the de-sired outputs at the thrusters the PID controller kickedin when it detected a disturbance in its position Testingthe propulsion system in the water gave positive results aswell the propeller held and the motor kept working whilesubmerged The response time performed adequately at anaverage of 50ms

KeywordsMechatronics Drone Underwater Self-stabilisation

ReferatDetta projektets syfte var att bygga en fjarrstyrd undervat-tensdronare med mjukvarustyrd sjalstabilisering for utvarderingav responstid framdrivningen och styrningen for att sevad som gar att uppna En prototyp byggdes och testa-des forst i torra forhallanden Prototypen har kontrollerasmed en Arduino och en Raspberry Pi som styr sex drivmo-torer Genom en kontroller kan anvandare styra farkostenoch om den utsatts for ovantade krafter kan mjukvaranmotverka dom Pa grund av risken for massivt elhaveri omvattentatningen inte ar tillracklig skots tester i vatten uppTyvarr gjorde detta att fullstandig optimering av mjuk-varan blev svar Resultaten i torr miljo var positiv syst-met utforde sin onskade funktion vid motorerna och PIDkontrollern forsokte stalla om positionen till ratta nar denmarkte av en felaktig position Propulsion systemet testa-des i vatten och gav positiva resultat ocksa propellern holloch motoren fortsatte fungera fastan sankt i vatten Re-sponstiden gav ett adekvat utfall pa ungefar 50 ms

NyckelordMekatronik Dronare Undervatten Sjalvstabiliserande

Acknowledgements

We would like to thank the teacher assistants who always helped and gave advicein the workshop as well as always spreading a positive vibe Our supervisor NihadSubasic for his feedback and guidance as well as the fellow students of the MF133Xcourse for valuable feedback on this report and the project in whole Special thanksto Hakan Gerner for his help and suggestions regarding the electrical componentsand configuration of the control units A special thanks aswell to Rouzbeh Delaverfor helping us figure out the small details in our codes which usually makes orbreaks the whole thing

Contents

1 Introduction 111 Project description 112 Inspiration 113 Development potential 214 Scope 2

2 Theory 321 Design 322 Mechanical forces 3

221 Buoyancy Force 4222 Thruster Forces 4

23 Control system 6231 Proportional-Integral-Derivative controller 6

3 Demonstrator 731 Design 732 Components 8

321 Chassis 8322 Thrusters 8323 Inertial Measurement Unit 9324 Control unit 10325 Camera module 11326 USB-controller 11

33 Electrical Circuit 12331 Waterproofing 13

34 Programming solutions 13341 Steering 14342 Controller implementation 15

35 Mechanics 15

4 Result 1741 Propulsion 1742 Steering 18

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 4: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

ReferatDetta projektets syfte var att bygga en fjarrstyrd undervat-tensdronare med mjukvarustyrd sjalstabilisering for utvarderingav responstid framdrivningen och styrningen for att sevad som gar att uppna En prototyp byggdes och testa-des forst i torra forhallanden Prototypen har kontrollerasmed en Arduino och en Raspberry Pi som styr sex drivmo-torer Genom en kontroller kan anvandare styra farkostenoch om den utsatts for ovantade krafter kan mjukvaranmotverka dom Pa grund av risken for massivt elhaveri omvattentatningen inte ar tillracklig skots tester i vatten uppTyvarr gjorde detta att fullstandig optimering av mjuk-varan blev svar Resultaten i torr miljo var positiv syst-met utforde sin onskade funktion vid motorerna och PIDkontrollern forsokte stalla om positionen till ratta nar denmarkte av en felaktig position Propulsion systemet testa-des i vatten och gav positiva resultat ocksa propellern holloch motoren fortsatte fungera fastan sankt i vatten Re-sponstiden gav ett adekvat utfall pa ungefar 50 ms

NyckelordMekatronik Dronare Undervatten Sjalvstabiliserande

Acknowledgements

We would like to thank the teacher assistants who always helped and gave advicein the workshop as well as always spreading a positive vibe Our supervisor NihadSubasic for his feedback and guidance as well as the fellow students of the MF133Xcourse for valuable feedback on this report and the project in whole Special thanksto Hakan Gerner for his help and suggestions regarding the electrical componentsand configuration of the control units A special thanks aswell to Rouzbeh Delaverfor helping us figure out the small details in our codes which usually makes orbreaks the whole thing

Contents

1 Introduction 111 Project description 112 Inspiration 113 Development potential 214 Scope 2

2 Theory 321 Design 322 Mechanical forces 3

221 Buoyancy Force 4222 Thruster Forces 4

23 Control system 6231 Proportional-Integral-Derivative controller 6

3 Demonstrator 731 Design 732 Components 8

321 Chassis 8322 Thrusters 8323 Inertial Measurement Unit 9324 Control unit 10325 Camera module 11326 USB-controller 11

33 Electrical Circuit 12331 Waterproofing 13

34 Programming solutions 13341 Steering 14342 Controller implementation 15

35 Mechanics 15

4 Result 1741 Propulsion 1742 Steering 18

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 5: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Acknowledgements

We would like to thank the teacher assistants who always helped and gave advicein the workshop as well as always spreading a positive vibe Our supervisor NihadSubasic for his feedback and guidance as well as the fellow students of the MF133Xcourse for valuable feedback on this report and the project in whole Special thanksto Hakan Gerner for his help and suggestions regarding the electrical componentsand configuration of the control units A special thanks aswell to Rouzbeh Delaverfor helping us figure out the small details in our codes which usually makes orbreaks the whole thing

Contents

1 Introduction 111 Project description 112 Inspiration 113 Development potential 214 Scope 2

2 Theory 321 Design 322 Mechanical forces 3

221 Buoyancy Force 4222 Thruster Forces 4

23 Control system 6231 Proportional-Integral-Derivative controller 6

3 Demonstrator 731 Design 732 Components 8

321 Chassis 8322 Thrusters 8323 Inertial Measurement Unit 9324 Control unit 10325 Camera module 11326 USB-controller 11

33 Electrical Circuit 12331 Waterproofing 13

34 Programming solutions 13341 Steering 14342 Controller implementation 15

35 Mechanics 15

4 Result 1741 Propulsion 1742 Steering 18

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 6: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Contents

1 Introduction 111 Project description 112 Inspiration 113 Development potential 214 Scope 2

2 Theory 321 Design 322 Mechanical forces 3

221 Buoyancy Force 4222 Thruster Forces 4

23 Control system 6231 Proportional-Integral-Derivative controller 6

3 Demonstrator 731 Design 732 Components 8

321 Chassis 8322 Thrusters 8323 Inertial Measurement Unit 9324 Control unit 10325 Camera module 11326 USB-controller 11

33 Electrical Circuit 12331 Waterproofing 13

34 Programming solutions 13341 Steering 14342 Controller implementation 15

35 Mechanics 15

4 Result 1741 Propulsion 1742 Steering 18

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 7: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

43 Response 18

5 Discussion and Conclusions 1951 Propulsion 1952 Response time 2053 Software 20

531 Construction and design 20532 Response and User Experience 21533 Improving the Design 21534 Appliances 22535 Conclusion 22

54 Authors Notes 23

Appendix A 25A1 Python Code 25A2 Arduino Main Program 31A3 Arduino Code for Data Parsing 36A4 Arduino Code for Sending Data 41A5 Arduino Code for PWM 43

Appendix B 47B1 Electrical Circuit 47

Bibliography 49

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 8: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

List of Figures

21 Motor configuration for acceleration turning and controlling yaw 422 Motor configuration for pitching and rolling 523 Propeller rotation for neutral torque on the ROVs body 5

31 Early 3D-model of the chosen design for the project made in Solid Edge 732 The PP pipe used for the chassis[12] 833 The DC-motor used[8] 934 The L298 dual H-bridge motor driver[10] 935 3D model of the propeller made in Solid Edge 936 The MPU-6050 IMU (6 DOF)[11] 1037 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13] 1038 The Sparkfun Bi-Directional Logic Level Converter [5] 1139 The Raspberry Pi Camera Module V2 [14] 11310 The Microsoft XBOX controller[9] 12311 Picture of the components on the plastic mounting board 12312 A logic diagram showing how the code functions 14313 The system of movement 14314 The function of the PID 15

41 The finished prototype 1742 Test of thruster propulsion in water 1743 Left Frame of input on controller Right Frame of motor activation 18

B1 The electrical circuit inside the ROV Made with [6] 47

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 9: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

List of Tables

1 Useful values symbol and units

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 10: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

List of Acronyms

DC Direct Current

FPS Frames per second

GPIO General Purpose Input Output

HDMI High Definition Media Interface

PID Proportional-Integral-Derivative

PP Polypropylene

PWM Pulse Width Modulation

ROV Remote Operated Vehicle

RPi Raspberry Pi 3 Model A+

UART Universal Asynchronous ReceiverTransmitter

USB Universal Serial Bus

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 11: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

List of units

Value Symbol UnitVolume V m3

Mass m kgDensity ρ kgm3

Acceleration a ms2

Gravitationalacceleration

g 9 82ms2

Buoyancyforce

B N

Torque T Nm

Table 1 Useful values symbol and units

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 12: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Chapter 1

Introduction

11 Project description

The project was to build an underwater Remote Operated Vehicle (ROV) alsoknown as a drone The ROV will be wired and controlled from the surface withnavigation aided by self stabilising software A camera will provide the user witha video feed from the ROV to help navigate and explore the surroundings It willneed to be waterproof and have a neutral buoyancy to traverse the waters as opti-mal as possible The design of the ROV will be optimised for ease of access and willact as a prototype for a finished product that would differ in design as this projectaims to explore the implementation and control of the mechanical components Thefollowing questions will be evaluated and tested

- What level of response time can be achieved for the user to feel a smooth ex-perience

- What level of steering manoeuvrability can be achieved underwater

- Will the drones propulsion be enough to navigate a submerged environmentadequately

12 Inspiration

ROVs and drones are becoming more frequently used both as hobby and in industrialuse Inspiration came from all the possibilities available to the useful tool that isan underwater drone such as inspecting or welding oil pipes studying underwaterecosystems or even rescue missions in water-filled caves The project also demandscreative and challenging solutions in both mechanical and electrical design It alsoserves as a good platform to build upon with implementation of more complexsteering and camera functions The opportunity to learn how to design for a non

1

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 13: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

optimal environment by building the drone for underwater use also contributed tothe choice of the project

13 Development potentialAs touched upon in the previous section the project has potential to be furtherdeveloped With more time and resources some extra functions such as a GPSa compass and a ultrasound detector etc could have been implemented Perhapssupport for virtual reality could be potential improvements The possibility ofpursuing these options someday greatly inspired the project

14 ScopeThe project was to be done between the middle of January to the beginning ofMay It has a budget limitation of 1000 kr (SEK) To keep the complexity down theROV will not be tested in open water Waterproofing of the ROV will be done tohighest achievable level but will primarily be tested out of water Fluid dynamicmeasurements of the ROVs body and propellers will not be done due to lack oftime knowledge and equipment

2

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 14: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Chapter 2

Theory

21 Design

The first great challenge in the project was choosing and designing the foundationof the ROV The design needed to fulfil these primary demands easy to constructeasy mechanical and electrical solutions and lastly water appropriate dynamics withwaterproofing Some key points were decided early and would be used regardless ofdesign The ROV would be wired and controlled with a Universal Serial Bus (USB)controller from the surface as wireless communication from underwater to surfacecan be difficult to implement It would also use this wire for a power feed To helpwith the steering a camera on board would stream video to the user

22 Mechanical forces

This section will discuss mechanical forces that affects the ROV In table 1 thecommonly used values and corresponding symbols and units are shown Note thatthe gravitational acceleration will be 9 82ms2 in all calculations

The design requires some mechanical calculations to determine how well it willtravel underwater hydrodynamics buoyancy force and thruster forces The hy-drodynamics is partly composed of fluid dynamic calculations which as discussedin the scope will not be done With the chosen design it was estimated to not bea big issue at the presumed speeds at which the ROV will travel But the as theROV is fully submerged the water will exert different forces on it Unfortunatelywater behaves far from predictable and is often not linear in its calculations It wastherefore hard to accurately asses the forces that affect the ROV without advancedmodels [15] Since this was only a prototype tested in shallow waters its ability tohandle higher water pressure at depths would also not be determined

3

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 15: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

221 Buoyancy Force

For optimal travel underwater a neutral buoyancy is preferable This means thatthe mass of the object is same as the mass of the displaced water This will hinderthe ROV from both sinking and surfacing by itself which otherwise would requireconstant adjustment from the thrusters to keep it in place The buoyancy of anobject is dependent on the volume of fluid that the object displaces and the densityof the fluid being displaced This means that

B = ρfluidV g (21)

where ρ is the density of the fluid V the displaced volume g the gravitationalacceleration (9 82ms2) and B the resulting buoyancy force As water is not com-pressible the density only varies slightly depending on temperature If taken intoaccount that the primary usage areas will be in freshwater with temperatures be-tween 0degC and 20degC the difference in density can be observed [16] as roughly 02With the volume of the ROV being constant the difference in buoyancy at differentwater temperatures can also be assumed constant as the density difference is verysmall For optimisation of the ROVs buoyancy force the density at 4degC will be usedthat is ρ = 1000kgm3

222 Thruster Forces

The thrusters consist of a motor and a propeller The propeller is rotated by themotor and pushes away water This applies an equal force on the propellers inthe opposite direction as per Newtons third law of motion making the motor (andthereby the body) move in the direction of the counteracting force By controllingwhich motors are active different movements of the ROV can be achieved

By activating the side motors with an equal amount of power movement for-wards and backwards is achieved If motors on one side are fed more power theROV will steer to the opposite direction To only rotate around its vertical axis theside motors are simply set to run with equal power in opposite directions Theseconfigurations can be seen in figure 21

Figure 21 Motor configuration for acceleration turning and controlling yaw

4

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 16: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

To control the pitch the vertical thrusters are regulated in pairs the front pairwork in the same direction and the back pair in the opposite This allows the ROVto be pitched to the desired angle while still moving forwards with the side motorsIn the same manner as the pitch the vertical motors on each side of the main tubecan work in pairs allowing the ROV to roll along its forward horizontal axis Motorinput for both manoeuvres are visualised in figure 22

Figure 22 Motor configuration for pitching and rolling

To make these movements the thrusters need to output sufficient force Calcu-lating thurster forces is a quite complex science and although there exists models[7] it is deemed outside of the scope of this project By using existing designs andadjusting them to fit the prototype a reasonable result should be expected

As mentioned before Newtons third law of motion states that every force appliedhas an equal counteracting force This also means that as the propellers rotate thecounteracting force on the propellers applies a torque on the motors which makesthe motor want to rotate Since the motors are attached to the body of the ROVthis means that the torque will aim to rotate the entire body To maintain a stableposition a counter torque needs to be applied If one thruster is rotating clockwisethe torque is countered by another one running counterclockwise This means thatthe overall torque on the body is neutralised if the thrusters are spinning in thedirections shown in 23

Figure 23 Propeller rotation for neutral torque on the ROVs body

5

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 17: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

23 Control systemThe control systems purpose is to allow the ROV to stabilise itself if any unwantedmovements occur This can be done in several ways By using the model that isdescribed in [1] the ROV can use a system that attempts to align itself to referencesystem Information that provides real-time data on the drones current positioncan be compared to the users input This allows the ROV to be able to positionand realign itself with the help of a control loop feedback system assuring a smoothvoyage It should be noted that models in [1] are designed for autonomous systemsThis project will only use stabilising and correction but with similar method ofthought Many different control loop feedback systems can be used for this purposewith some discussed in [3] With previous experience with one of the discussedcontrollers the decision to use a Proportional-Integral-Derivative (PID) was madeAs the paper states it might have problems with the response time giving the usera harder time to control the ROV This is something that can be improved throughexperimentation due to how a PID controller works

231 Proportional-Integral-Derivative controllerA Proportional-Integral-Derivative (PID) is a control loop feedback system Itworks by taking the error that exists in a system for example a misalignment anduses that error to rdquopushrdquo the system back into its place A general expression for aPID-controller is

u(t) = Kpe(t) +Ki

int t

0e(tprime)dtprime +Kd

de(t)dt

(22)

where e(t) is the error at the time t Kp KI and Kd are constant values thatare optimised through testing The output u(t) is the correction that needs to bemade at the given time t The three parts of the PID are mentioned in its nameThe proportional part is straightforward in that it takes the error as it is and triesto use that value to rdquojumprdquo back This can cause the system to oscillate jumpingback and forward but not settling in the desired state

The other two parts seek to amend that the derivative part using the rate ofchange in error and wanting to reduce that to zero The integral part using thehistory of errors in order to anticipate what comes after The derivative part isexcellent at quickly changing the system which makes it fast at aligning the systembut can often exacerbate the oscillation While the integral part although slowerthan both the proportional part and the derivative part of the controller can nullifythe oscillation from those parts

6

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 18: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Chapter 3

Demonstrator

31 Design

Satisfying the demands on the design led to several solutions that all excelled onsome points but fell short on others In the end the design visualised in 31 waschosen

Figure 31 Early 3D-model of the chosen design for the project made in SolidEdge

The design uses tubes for its chassis maintaining easy construction while alsogenerating a significant buoyancy force Wires are easily fed through the pipesEase of access is somewhat compromised but with removable ends this is not toobig of an issue Although there are a few joints these can easily be sealed withsilicone to waterproof them The placements of the vertical thrusters allow for greatmanoeuvrability such as pitching rolling and fully vertical surfacing and divingThe horizontal thrusters allow the basics of turning and accelerating

7

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 19: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

32 Components

Below will be short explanations of each critical part and what role they played inthis construction

321 Chassis

The chassis will be a simple design with a main Polypropylene (PP a plastic poly-mer) body connected to two smaller tubes on each side The main tube has adiameter of 75 mm and a length of 600 mm while the side tubes are 50 mm diam-eter and 500 mm long The connecting parts will also be two PP pipes but witha smaller diameter of 32 mm one on the front and one in the back Using plas-tic pipes provides a low weight waterproof solution with plenty of room internallyfor electrical components and wiring With the help of silicone all tube joints andopenings for wires are easily waterproofed

Figure 32 The PP pipe used for the chassis[12]

322 Thrusters

The thrusters are the backbone of the ROV They are controlled in two ways -by the user and by self regulating software The thrusters are DC-motors with apropeller attached to the shaft and uses a dual H-bridge motor driver allowing themotors to rotate in both directions In total six thrusters are to be used two forhorizontal propulsion and four for vertical propulsion

DC-motor stands for direct current motor and uses direct current to outputmechanical energy with the help of magnetic fields created inside the motor TheDC-motors[8] used are 6V and up to 14500 rpm and are seen in figure 33 Theysit in a waterproofed case with the shaft slightly exposed to the water Due tocomplications with fully sealing moving parts some drops of water may slip throughThe speed of the motors is regulated with Pulse Width Modulation (PWM) PWMis a method to regulate the average voltage output by turning the load on and offin short intervals The longer the load is on the higher the average output will be

8

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 20: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Figure 33 The DC-motor used[8]

An H-bridge is a circuit that with the help of transistors can switch the polarityof voltage running through it This means the polarity over the DC-motor can beswitched allowing the motor to run backwards as well This is very useful for theROV since it needs to be able to move in all directions This is done with threeL298 dual H-bridge motor drivers [10] for its six motors and can be seen in figure34

Figure 34 The L298 dual H-bridge motor driver[10]

When looking at the final part of the thrusters the propeller the choice early onwas between 3D-printing and buying a finished product Buying a finished productwould give the luxury of knowing that it will work fine but with less customisationregarding sizes 3D-printing on the other hand provides full control over size andshaft fits although its strength may suffer Ultimately the choice fell on 3D-printingas the need for customisation seemed like the greater issue The model shown infigure 35 was designed similar to known working products

Figure 35 3D model of the propeller made in Solid Edge

323 Inertial Measurement UnitAs the user will be aided in steering by software the software needs some input todetermine how and when to act Suitable input would be acceleration and rotation

9

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 21: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

along all axes in a three dimensional system The MPU-6050[11] contains both anaccelerometer and gyroscope used for measuring these values The MPU-6050 isshown in figure 36

Figure 36 The MPU-6050 IMU (6 DOF)[11]

324 Control unit

Two different units were considered at the beginning an Arduino Uno [2] and aRaspberry Pi 3 Model A+ (RPi) [13] as seen in figure 37 Arduino runs codedirectly installed on its flash drive and Raspberry Pi runs code through its operatingsystem Since the Arduinos code works closer to its hardware it handles operationsquicker The Arduino Uno offers more PWM outputs but fewer General PurposeInput Output (GPIO) pins overall However the RPi has both a USB port fora controller and an HDMI port for streaming video It also has an own cameramodule that easily can be configured By using both controllers they can worktogether while individually handling the parts they do best

Figure 37 The Raspberry Pi 3 Model A+ and the Arduino Uno[2][13]

The RPi handles the camera feed controller input and sets the directions of themotor drivers Input data from the controller is then transmitted with the helpof Universal Asynchronous ReceiverTransmitter (UART) a hardware for serialcommunication As the devices use different voltage levels for their pin outputs alogic level converter [5] was used and is seen in figure 38 This simply converts thevoltage levels so that the devices can communicate through their GPIO pins

10

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 22: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Figure 38 The Sparkfun Bi-Directional Logic Level Converter [5]

When the data is recieved on the Arduino it is read and corresponding PWMoutput is made The MPU-6050 is also connected to the Arduino providing theacceleration and rotation of the ROV The Arduino hosts the PID controller whichcan tell the RPi to switch motor rotation direction if needed

325 Camera module

With the choice of Raspberry Pi as the micro controller the choice of camera modulenaturally fell on Raspberry Pirsquos own camera module[14] seen in figure 39 It featuresvideo in 1080p resolution at 30 Frames per second (FPS) or 720p at 60 FPS whichboth work fine for the project

Figure 39 The Raspberry Pi Camera Module V2 [14]

326 USB-controller

To give the user maximum control over the ROV it was decided that a full con-troller was needed instead of keyboard input A controller lets the user do smalladjustments in steering as the joysticks allow finer input Fortunately a MicrosoftXBOX-controller as seen in figure 310 with an USB-adapter was already ownedand available for use in the project The controllers main features are two joysticksand two rdquotriggerrdquo buttons that are able to interpret how far down the button ispressed Movement will be controlled with the joysticks whereas acceleration willbe done with the trigger buttons It also has several regular buttons that simplywork in a onoff state useful for camera controls locking speed etc

11

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 23: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Figure 310 The Microsoft XBOX controller[9]

33 Electrical Circuit

With the components selected the next step was connecting them Some compo-nents are easier than others - the USB controller and camera module were simplyconnected to the corresponding ports on the RPi The rest of the components wereconnected to power supplies and GPIO ports on the Arduino and RPi In appendixB1 the full electrical circuit can be seen Voltage inputs on the Arduino and RPi is5 V through their respective USB-ports while the 12 V input to the motor driversis from a 12 V DC converter connected to a 230 V wall socket With more time andknowledge these voltage inputs could have been configured to come from the samesource reducing the number of wires needed between the ROV and the user Tofurther reduce the cables this voltage output could be a battery on board Since allcomponents needed to fit inside a tube the motor drivers IMU and a connectorboard wree mounted on a plastic plate This plate was held in place inside the tubewith the help of two circular plates with the same diameter as the inside of thetube The solution is seen in fig 311

Figure 311 Picture of the components on the plastic mounting board

12

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 24: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

331 Waterproofing

One of the bigger hurdles of this project is keeping the water on the outside ofthe chassis so the electrical components stay dry on the inside There are two keyfactors that advance the difficulty Firstly the rotating shafts of the motors needto move freely to be effective and secondly the ability to access the interior of theROV for adjustments and altercations

For the shaft problem the solution will simply be to fit the motors in a casingand then sealing as good as possible with glue that reacts well with PP-plasticSome drop of water may find its way inside near the shaft but should not interactwith electrical current By letting any possible leaked water fully dry after use andkeeping the internals of the motors well greased the potential shaft sealing leakshould be manageable

Due to the material consisting mainly of thermoplastics the joints were weldedtogether The other parts being PLA and acrylic was glued on to the PP-plasticA silicone rubber tape was added for extra leakage stopping around the motors andends of the tubes

34 Programming solutions

The backbone of this drone consists of two important functions which enable itto navigate its nautical environment and allows the user to accurately control theconstruction Steering and Stabilisation

To let both these functions work properly one important thing is needed in theform of a coordination system supplied by the IMU in the form of an angular-systeminstead of a xyz-system

The programs here are run in Python on the Raspberry and C++ on the Ar-duino

13

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 25: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Figure 312 A logic diagram showing how the code functions

341 Steering

The drone consists as before discussed of six thrusters two responsible for the yawand transverse movements and four controlling the pitch roll and altitude

Figure 313 The system of movement

Intuitively by seeing the picture the robot can only move through combinationsof the thrusters Putting this in the program if statements were designed for everymovement In the case of the yaw movement the 5th and the 6th thruster needs

14

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 26: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

to switch direction or speed depending on the direction The roll movement needsthat the 1st and the 3rd thruster are opposite to the 2nd and the 4th and naturallythe pitch movement requires that the 1st and 2nd thruster are opposite to the 3rdand 4th Lastly to achieve forward movement the 5th and 6th thruster need tonaturally be switched on and for the drone to change altitude all the thrustersexcept the last two (5 and 6) need to do work

342 Controller implementationThe ROV will always be subject to unexpected forces in the water Should thoseproblems not be amended the user would experience failure in the control responseor a dissatisfying experience in piloting the drone A PID controller was used tosolve those issues By calculating the error in what the drone thinks it should bedoing versus with what it is doing the PID can reduce that error in order to regulatethe drone The implementation of the PID was fairly basic as no physical modelwas used and instead a decision was made to determine coefficients experimentallywas made

Figure 314 The function of the PID

Using a PID library for Arduino [4] three different PIDs were designed one forpitch one for roll and one for yaw with its own set of separate values The values thePID used being the values the IMU outputs chiefly the degree of rotation in the x-(pitch) y-(roll) and z-(yaw)axis Once the user starts inputting a command throughthe Xbox controller the PID momentarily stops calibrating in the direction beingmanipulated once again resuming once the user stops putting in more commandsOnce it starts again it receives a new set point from the IMU depending on its newstate and once again tries to regulate the drone to stabilise to the new set points

35 MechanicsWith the ROV built the volume can be calculated and the mass measured Withthe volume and mass of

V = 0 00443m3 (31)m = 1 63kg (32)

15

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 27: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

the buoyancy force can be calculated with the help of equation 21 With ρ as1000 kgm3 and the volume of the ROV the buoyancy force on acting on the bodyof the drone is

B = 1000kgm3 middot 0 00443m3 middot 9 82ms2 = 43 5N (33)

and considering the force exerted by gravity amounts to 1 63kg middot 9 82ms2 = 16N 28 kg of extra weight needed to be added to achieve neutral buoyancy This wasdone with metal rods inside the side tubes

16

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 28: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Chapter 4

Result

Figure 41 The finished prototype

41 Propulsion

By first testing a thruster in a bucket of water (figure 42) the 3d-printed partsproved sturdy enough to the forces assailing it in the water and did not tear itselfapart or rupture The DC motor did not experience failure from water leakagesignifying the case providing a secure environment for the motor The full prototypewas then tested in a bathtub with the system being able to propel it well enoughAfter around five minutes of testing the drone was extracted from the tub and wasstill in a working condition the day after

Figure 42 Test of thruster propulsion in water

17

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 29: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

42 SteeringInputting into the controller the drone was able to readjust the directions andvoltage output of its motors The drone was able to produce the movements shownin fig 314 but with difficulties while submerged due to its weight

The PID controller also changed the drones state depending on the positioningof the drone from where it first was started The different responses are depictedin figure

Finally together the user and the PID were in tandem able to adjust the positionof the drone the user having priority always and the PID controller self adjustingthe drone based on whatever input the user had finished making

43 ResponseThe response of the system depends on four variables the input from the Xboxcontroller the baudrate between the Arduino and the Raspberry Pi the packagedelay set in the code and the function that parses the data in the Arduino

Theoretically adding the different delays from the input from the controller andthe various delays through the code an average of 40ms delay was expected

Using a camera filming at 480 FPS the action on the controller and the activationof the motor was recorded seen in figure 43 In a video editing software therecording could be viewed frame by frame (each frame captured every 21 ms)Several tests yielded an average response time of 47 ms

Figure 43 Left Frame of input on controller Right Frame of motor activation

18

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 30: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Chapter 5

Discussion and Conclusions

51 Propulsion

There were several problems facing the thrusters because of time and budget con-straints and the limitations of the compromises that had been made of the design

Firstly the propellers were not bought nor made with careful dimensioning theywere only made based on existing submarine propellers They were then 3D-printedwhich for the parts that will endure most of the load is sub-optimal The stresseson the blades can cause tearing on them during work which is a worrying problemSince the propellers design suffers from a lack of scientific base inefficiency couldbe a problem

There is also the problem with water leakage As the motors are not water-proofed even with the measures taken sealing the rotating shaft and covering thecases with a coat of paint water would still probably enter the motor shorteningits lifespan During this project the problem did not present itself overtly

There is also the problem of cavitation because the motors used had no settingsin which the speed could be adjusted except for regulating the voltage through thePWM the rpm would always be high The drone would because of this effect movejerkily and erratically hampering the user experience and also affecting the PIDcontroller Effectively causing a sort of turbulence

The power output was not sufficient in providing power completely to the motorswith full power not being accessible with the current provided from the adapterand the drone having stuttering problems when executing all the movements at thesame time

To solve these issues either the scope must be expanded to include these prob-lems or the budget increased to buy proper thrusters The drone did work but thedegree of its functionality was impaired because of the aforementioned issues

19

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 31: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

52 Response timeThe Xbox controller has a native delay of around 15 ms before the Raspberry Pistarts receiving data from it This was tested in the same way as described in rdquoRe-sultsrdquo but with the RPi printing the data when it was received The latency of themonitor had to be removed also This time is acceptable but could be improvedwith a better controller

Adjusting the Baud rate between the RPi and the Arduino can have a differingeffect on the response Lowering it causes the chips to communicate at a slowerspeed lowering the smoothness of input but at the same time alleviating the pres-sure of the chip receiving and parsing the data The code was tested until a goodmedium was found and a baud rate of 19200 bds was found to have a good effecton the data readability and the speed of response To further increase the readabil-ity of the data and reduce faulty parsing delays were introduced in several parts ofthe code On the RPi a 10 ms delay when sending the data and on the Arduino a1 ms delay for parsing the packages being sent These values ensured that the datawas sent correctly and saved correctly

53 SoftwareLooking at the code several iterations were made in order to craft a system forwhich the user would feel a natural inclination and intuition toward the drone Todecrease the response delay to make it user friendly and to let it bring enjoyment

Several adjustments could have been made to improve the functionality of thesoftware A physical model could have been derived to accurately describe a betterPID controller that would improve the regulation of the drone even further Thecode itself was constructed ground up but parts of it was derived from resourcesfound on the internet as well as existing libraries

But in the end the software was not made by expert hands causing it to sufferfrom inconsistencies that required greater troubleshooting With time these couldhave been solved but naturally new problems would spring up so a cut off had tobe made where the system works aptly Lastly the MPU-6050 suffered from a flawin where the reported value coming from the chip drifts even though it is standingstill In other words the drone would think it was performing a yaw movementeven though it would not This could have been solved with a magnetometer beingimplemented in the hardware

531 Construction and design

During the project several cutbacks were made with the design that was proposedfrom the get go and the construction which was planned upon

The design itself was re-imagined from a lightweight design with little materialoverlap to a bulky form with the PP tubes This itself would shape the project

20

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 32: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

in many ways because of the form and space issues that were raised from it Thechips and the breadboard had to fit inside the main tube and the wiring had todrawn inside the bulky frame

The propellers themselves had to be fitted with 3D printed casings in orderto seal them from water and to fit them inside the outside tubes Unfortunatelybecause of the conflicting forms of the DC-motor and the bulky PP tubes therewas no space to design a water channel for the thrusters

In the end a compromise was made to have no channel at all and instead likean airborne drone let the propellers protrude outside the tube instead of beingcontained in a water channel inside the tube

Other minor problems plagued the construction because of the aforementionedcompromises that were made and solving them meant moving further away from theconcept outlaid in the planning stage New problems arose later on when finishingthe construction The plastics being of different types would not adhere to eachother properly even with a proper type of glue causing water leakage and weakpoints The drones volume was also exaggerated causing unnecessary amounts ofweights needing to be added to cause neutral buoyancy Finally because of therestrictions and inefficiencies in space caused by the tubes the wiring had a hardtime fitting inside causing loose wires troubling the drone during testing

532 Response and User Experience

Response time is all important throughout this project the user needing to be ableto steer the vehicle as if themselves were sitting inside it controlling it The projectdid reach a satisfying level in response time but with room to improve

Testing revealed the average response time to be around 50ms with some vari-ance A human has an average reaction time of 200ms so if something wouldthreaten the trajectory of the drone the user has to be able to react accordinglyThat means the having a delay as close to zero as possible Of course that is im-possible to reach But a goal of this project was to hit around 50 ms which wasmostly achieved with an average of around 40 ms being hit

Unfortunately because of loose wiring and unoptimised code the delay some-times suffers from variance that would push the response rate to an upwards of500ms But with enough time those problems can be eliminated as well

533 Improving the Design

At the planning stage several thoughts were made on what design the drone wouldhave Some alternatives were a ROV driven by pumps instead of propellers andanother design was a ROV with four propellers that were able to rotate and readjustalong its axle

In the end the choice was made to go with a more stiff design because of theease of construction and the simple form being intuitive to control

21

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 33: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Two of the biggest improvement that can be made with this project is con-structing a more lighter frame not consisting of PP tubes but of tightly formedconstruction that is not impaired by the hydrodynamics and to actually model itand simulate it With a physical model a even better control loop feedback mech-anism could be implemented allowing even better stabilisation and maybe in thefuture even automation With a specially designed physical framework the dronecould be tailor made to closer resemble the concept stage

With drones there are many possibilities which leaves a great regret that moretime could not have been spent on it

534 AppliancesMaybe the most important part of the discussion is where the drone can be usedA lot of the questions that were raised were about the users enjoyment level andthe ease of access and response But drones have multifaceted areas of use thatstretches beyond personal recreation A water drone could access places a personwould have difficulty reaching It could help with rescue missions survey oil spillsand other damages to nautical areas gather information about marine life and beused to monitor the oceans The earth is covered with water about 70 and ahaving drones help explore our own world while not disturbing the habitat of thosethat live in those areas would be invaluable

535 ConclusionWith the constraints set upon the project the drone reached an acceptable level offunctionality But not enough for it to reach its intended destination the deep seaThis project set out to prove that a drone can be designed with the ideas put forwardand the materials provided and while yes it does work it will require furtheriteration and experimentation until a level can be reached for it to satisfyinglyperform its intended role and functions

The response rate has to be low the propulsion fast the steering flexible andthe construction sturdy With those goals completed the drone would be finalised

22

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 34: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

54 Authors NotesClosing thoughts creating this drone was a task that was fulfilling and yet left uswanting more The nature of this project was that it felt at all times that it hadroom to improve to expand and become more At the beginning there were manyideas floating in the void of the mind and to distil those thoughts and make themreality was the real magic of this project

At the start of the project so many ideas were put forward but at the end wewere content to just see it work The excitement of first seeing that propeller moveand at last submerging it into water was indescribable A terror at first of theanticipation of seeing your creations first foray into its mission The feeling of joywhen it works a determined mind willing to solve the problem when it didnrsquot Wewould like to thank those that helped us create this drone who believed in us whenwe ourselves didnrsquot Thank you KTH for allowing us the chance to experience thisproject letting us stumble and learn and for letting us create our own piece nomatter how small or insignificant it was

23

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 35: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Appendix A

A1 Python Code

Listing A1 Raspberry Pi python codeSharkbait Main Program RPiVictor HaneforsDate 20190604 version 3GoalThis code will read whatever is being inputted into the xboxcontroller send those values to the Arduino through the logic

rarr lever converterand meanwhile change the directions by defining if statements with

rarr the samevalues taken from the xbox controller to determine those directions

rarr andsending that to the motor drivers

usrbinenv python

import RPiGPIO as GPIOimport timeimport serialimport xbox

Runs at startup and sets up the serial com controller and GPIOrarr pins

Class for pins used for motor direction control

25

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 36: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

class motorPinsdef __init__(self)

The H-bridge takes 2 inputs per motorselfp5 = [1613 ] 1613 5selfp3 = [6 5] 65 3selfp2 = [20 21] 20 21 2selfp1 = [19 26] 19 26 1selfp6 = [11 7] 11 7 6selfp4 = [8 25] 8 25 4

def GPIOsetup(pins)GPIOsetmode(GPIOBCM)GPIOsetwarnings(False)GPIOsetup(pinsp1 GPIOOUT)GPIOsetup(pinsp2 GPIOOUT)GPIOsetup(pinsp3 GPIOOUT)GPIOsetup(pinsp4 GPIOOUT)GPIOsetup(pinsp5 GPIOOUT)GPIOsetup(pinsp6 GPIOOUT)GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))

Formats the value given from the controller copied from githubrarr xbox library

def fmtFloat(n)return rsquo63frsquoformat(n)

def recieve_input()Recieve inputs from controller and retrun the corresponding

rarr values

transversal=(joyrightTrigger()-joyleftTrigger())

roll=joyleftX()print(roll)yaw=joyrightX()print(yaw)Vertical mode if right bumper is pressed otherwise pitch

rarr modeif joyrightBumper()

vertical=joyleftY()pitch=0

elsepitch=joyleftY()

26

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 37: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

vertical=0

return pitch roll yaw transversal vertical

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def pitch_func(inputPitch)if inputPitch gt 0 pitch up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

elif inputPitch lt 0 pitch downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def roll_func(inputRoll)if inputRoll gt 0 Right Roll

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH)) -GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW)) +GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH)) -

elif inputRoll lt 0 left RollGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def yaw_func(inputYaw)

27

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 38: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

if inputYaw gt 0 Right turnGPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

elif inputYaw lt 0 left turnGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def trans_func(inputTransversal)if inputTransversal gt 0 forward

GPIOoutput(pinsp5 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp6 (GPIOHIGH GPIOLOW))

elif inputTransversal lt 0 backwardsGPIOoutput(pinsp5 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp6 (GPIOLOW GPIOHIGH))

Setting the direction of motors depending on input value then sendrarr the input value to Arduino for PWM control

def vertical_func(inputVertical)if inputVertical gt 0 up

GPIOoutput(pinsp1 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp2 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp3 (GPIOHIGH GPIOLOW))GPIOoutput(pinsp4 (GPIOHIGH GPIOLOW))

elif inputVertical lt 0 downGPIOoutput(pinsp1 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp2 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp3 (GPIOLOW GPIOHIGH))GPIOoutput(pinsp4 (GPIOLOW GPIOHIGH))

Sends the buttondirection input and value to Arduino for PWMrarr control

def sendPWM(buttonvalue)serwrite(lt+button++fmtFloat(value)+gt)timesleep(001)

Cleaning up and shutting down smoothly

28

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 39: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

def shutdown()print(Programshuttingdown)joyclose()print(ControllerOFF)GPIOoutput(pinsp1 (GPIOLOW GPIOLOW))GPIOoutput(pinsp2 (GPIOLOW GPIOLOW))GPIOoutput(pinsp3 (GPIOLOW GPIOLOW))GPIOoutput(pinsp4 (GPIOLOW GPIOLOW))GPIOoutput(pinsp5 (GPIOLOW GPIOLOW))GPIOoutput(pinsp6 (GPIOLOW GPIOLOW))GPIOcleanup()print(MotorsOFF)

def pid_input()while serinWaiting()

data=serreadline()if data[0]==

data=datasplit()print(data)pitch=data[1]roll=data[2]yaw=data[3]transversal=data[4]vertical=data[5]return pitch roll yaw transversal vertical

elsereturn 00000

Main function runs the input checks sets motor directions sendsrarr PWM data

See comments on functions for further explanationdef main_func_steering()

trywhile not joyBack()

Receive input from controller and PIDpitch roll yaw transversal vertical =

rarr recieve_input()

if (pitch ==0 and roll == 0 and yaw ==0 andrarr transversal == 0 and vertical == 0 )

pitch roll yaw transversal verticalrarr = pid_input()

29

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 40: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

sendPWM(LY0)sendPWM(LX0)sendPWM(RX0)sendPWM(RTLT0)sendPWM(RB0)

elseSends PWM datasendPWM(LYpitch)sendPWM(LXroll)sendPWM(RXyaw)sendPWM(RTLTtransversal)sendPWM(RBvertical)

Set the motor directions and sends PWM datapitch_func(pitch)roll_func(roll)yaw_func(yaw)trans_func(transversal)vertical_func(vertical)

shutdown()

except KeyboardInterruptshutdown()

tryprint(Programstarting)Setup for serial communication with Arduino Unoser = serialSerial(

port=rsquodevserial0rsquobaudrate= 19200parity=serialPARITY_NONEstopbits=serialSTOPBITS_ONEbytesize=serialEIGHTBITStimeout=0

)print(Serialsetupcomplete)Using the xboxpy library the controller is initiatedjoy=xboxJoystick()if joyconnected()

print(Controllersetupcomplete)else

print(Controllerissetupbutnotconnected)Setting up the GPIO pinspins=motorPins()

30

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 41: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

GPIOsetup(pins)print(GPIOsetupcomplete)

finallyprint(Programstartedsuccesfully)timesleep(05)

main_func_steering()

A2 Arduino Main Program

Listing A2 Main Arduino programMain Code for the droneShaya RahmanianDate 20190604 version 4GoalThis program will run the other codes attached to it whilebeing able to insert delays for the different functions in order

rarr toassess the responsetimeThe PID and the MPU6050 (IMU) will also be monitored and executedby this code

include ltPID_v1hgtinclude ltWirehgtinclude ltMPU6050_tocknhgt

declare various pinsdefine PIN_OUTPUT1 3 3 writing down pin ports in case of PWM

rarr cables getting mixed updefine PIN_OUTPUT2 5 5define PIN_OUTPUT3 10 6define PIN_OUTPUT4 11 9define PIN_OUTPUT5 6 10define PIN_OUTPUT6 9 11

declare for the MPUMPU6050 mpu6050(Wire)

31

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 42: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

declare for the PIDDefine Variables wersquoll be connecting todouble Setpoint1 Setpoint2 Setpoint3 PIDInputP PIDInputR

rarr PIDInputY PIDOutputP PIDOutputR PIDOutputYint aspd = 80

Specify the links and initial tuning parametersdouble Kp_yaw=0 Ki_yaw=0 Kd_yaw=0double Kp_pitch=1 Ki_pitch=0 Kd_pitch=0double Kp_roll=1 Ki_roll=0 Kd_roll=0

declare the different motions for the PIDsPID ROV_pid_pitch(ampPIDInputP ampPIDOutputP ampSetpoint1 Kp_pitch

rarr Ki_pitch Kd_pitch DIRECT)PID ROV_pid_roll(ampPIDInputR ampPIDOutputR ampSetpoint2 Kp_roll

rarr Ki_roll Kd_roll DIRECT)PID ROV_pid_yaw(ampPIDInputY ampPIDOutputY ampSetpoint3 Kp_yaw Ki_yaw

rarr Kd_yaw DIRECT)

declare various stuff for the serial IO so we getsend dataconst byte numChars = 32 size of the temporary array used to

rarr store the received dataconst byte numSmoo = 1 size of the temporary array used to store

rarr the parsed datachar receivedChars[numChars] temporary array for use when

rarr receiving datachar tempChars[numChars] temporary array for use when parsing

variables to hold the parsed datachar messageFromPI[numChars] = 0int integerFromPI = 0float floatFromPI = 00int pitch_state roll_state yaw_state trans_state vert_stateint vert_switchfloat pitch_acc[numSmoo] roll_acc[numSmoo] yaw_acc[numSmoo]

rarr trans_acc[numSmoo] vert_acc[numSmoo]int bEWP = 30

unsigned long previousMillis1 previousMillis2 previousMillis3 = 0rarr save millis used to clear data

const long interval1 = 001 interval to check received data (ms)const long interval2 = 01 interval to update the speed (ms)const long interval3 = 5 interval to send data (ms)

32

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 43: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

boolean newData = false

variables for the acceleration and numSmoothing of itfloat savedPitch savedRoll savedYaw savedTrans savedVertfloat pAcc rAcc yAcc tAcc vAccfloat plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAveragefloat pInputAcc rInputAcc yInputAcc tInputAcc vInputAcc

void setup()

startup with the baudrate and MPU6050

Serialbegin(19200) set baudrate for signalWirebegin()

mpu6050begin()mpu6050calcGyroOffsets(true)pitch_state roll_state yaw_state trans_state vert_state = 0

set the pinspinMode(PIN_OUTPUT1 OUTPUT)pinMode(PIN_OUTPUT2 OUTPUT)pinMode(PIN_OUTPUT3 OUTPUT)pinMode(PIN_OUTPUT4 OUTPUT)pinMode(PIN_OUTPUT5 OUTPUT)pinMode(PIN_OUTPUT6 OUTPUT)plastAverage rlastAverage ylastAverage tlastAverage

rarr vlastAverage = 00

PIDInputP = mpu6050getAngleY() get yaw roll and pitchrarr values from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()Setpoint1 = mpu6050getAngleY()Setpoint2 = mpu6050getAngleX()Setpoint3 = mpu6050getAngleZ()

turn the PID onROV_pid_pitchSetOutputLimits(-9090)ROV_pid_rollSetOutputLimits(-9090)

33

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 44: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

ROV_pid_yawSetOutputLimits(-9090)

ROV_pid_yawSetMode(AUTOMATIC)ROV_pid_pitchSetMode(AUTOMATIC)ROV_pid_rollSetMode(AUTOMATIC)

Serialprint(readytogo)get the values for the different inputs

void loop() ===========================================MPU6050 data===========================================mpu6050update()

============================= Pid controller calibration=============================

PIDInputP = mpu6050getAngleY() get yaw roll and pitch valuesrarr from our MPU6050

PIDInputR = mpu6050getAngleX()PIDInputY = mpu6050getAngleZ()ROV_pid_yawCompute() compute for the PIDROV_pid_pitchCompute()ROV_pid_rollCompute()

===========================================our functions for the serial IO===========================================recvWithStartEndMarkers()

unsigned long currentMillis = millis()

if (currentMillis - previousMillis1 gt= interval1)

save the last time you blinkedpreviousMillis1 = currentMillis

if (newData == true) strcpy(tempChars receivedChars)

this temporary copy is necessary to protect therarr original data

34

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 45: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

because strtok() used in parseData() replaces therarr commas with 0

parseData()showParsedData()saveData_func()newData = false

Serialprintln(pitch_acc[0])===========================================Convert the values from the PID or controller into PWM analog

rarr values===========================================if (currentMillis - previousMillis2 gt= interval2) check each intervalpreviousMillis2 = currentMillis

WIP smoothing functions pitch_state= checkstate_func(pitch_acc numSmoo) pAcc = smoothing_func(pitch_state plastAverage) pAcc = pitch_state 100 roll_state= checkstate_func(roll_acc numSmoo) rAcc = smoothing_func(roll_state rlastAverage) yaw_state= checkstate_func(yaw_acc numSmoo) yAcc = smoothing_func(yaw_state ylastAverage) trans_state= checkstate_func(trans_acc numSmoo) tAcc = smoothing_func(trans_state tlastAverage) vert_state= checkstate_func(vert_acc numSmoo) vAcc = smoothing_func(vert_state vlastAverage)

pAcc = abs(pitch_acc[0]) aspdrAcc = abs(roll_acc[0]) aspdtAcc = abs(trans_acc[0])aspdyAcc = abs(yaw_acc[0])aspdvAcc = abs(vert_acc[0])aspd

switch the PID on or off depending on the controller state WIPrarr PROBLEM WITH SET POINT WHEN CHANGING PITCH

if ( pitch_acc[0] =0) ROV_pid_pitchSetMode(0) Setpoint1 = mpu6050getAngleY()

35

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 46: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

else ROV_pid_pitchSetMode(AUTOMATIC) pAcc = (abs(PIDOutputP) 90) 400 if ( roll_acc[0] =0) ROV_pid_rollSetMode(0) Setpoint2 = mpu6050getAngleX() else ROV_pid_rollSetMode(AUTOMATIC) rAcc = (abs(PIDOutputR) 90) 400 if (( yaw_acc[0] =0) || (trans_acc[0] = 0)) ROV_pid_yawSetMode(0) Setpoint3 = mpu6050getAngleZ() else ROV_pid_yawSetMode(AUTOMATIC) yAcc = (abs(PIDOutputY) 90) 255

=============================================================Send either the PID value or the controller value to our pins=============================================================if (currentMillis - previousMillis3 gt= interval3) previousMillis3 = currentMillis

int pDir = direction_func(Setpoint1 mpu6050getAngleY())int rDir = direction_func(Setpoint2 mpu6050getAngleX())int zDir = direction_func(Setpoint3 mpu6050getAngleZ())

sendData_func(pDir rDir zDir)

pin_func(pAcc rAcc yAcc tAcc vAcc)

A3 Arduino Code for Data Parsing

Listing A3 Serial Receiver from RPiData ParseShaya Rahmanian

36

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 47: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Date 20190604 version 4GoalThis code will read the serial print being sent from the RPithrough the logic level converter and parse that data for the

rarr main programto use The data being whatever being inputted into the Xbox

rarr controllerIt will also have a buffer array for the values being stored

rarr wherethe mainprogram can define the size of those arrays Mainly used

rarr to combatbad values from the serial print being read

=====================================================void recvWithStartEndMarkers() gets the data in the form of lt

rarr input datagtstatic boolean recvInProgress = falsestatic byte ndx = 0char startMarker = rsquoltrsquochar endMarker = rsquogtrsquochar rc

while (Serialavailable() gt 0 ampamp newData == false) rc = Serialread()

if (recvInProgress == true) if (rc = endMarker)

receivedChars[ndx] = rcndx++if (ndx gt= numChars)

ndx = numChars - 1

else

receivedChars[ndx] = rsquo0rsquo terminate the stringrecvInProgress = falsendx = 0newData = true

else if (rc == startMarker) recvInProgress = true

37

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 48: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

=========================================================void parseData() split the data into its parts

char strtokIndx this is used by strtok() as an index

strtokIndx = strtok(tempChars) get the first part - therarr string

strcpy(messageFromPI strtokIndx) copy it to messageFromPI

strtokIndx = strtok(NULL ) this continues where therarr previous call left off

integerFromPI = atoi(strtokIndx) convert this part to anrarr integer

strtokIndx = strtok(NULL )floatFromPI = atof(strtokIndx) convert this part to a float

============================================================

void showParsedData() just for testingSerialprint(Message)Serialprintln(messageFromPI)Serialprint(Integer )Serialprintln(integerFromPI)Serialprint(Float)Serialprintln(floatFromPI)

===============================================================void saveData_func() saves the data depending on the different

rarr inputs into their own arraysstatic byte pdx rdx ydx tdx vdx = 0

if ((strcmp(messageFromPI LY) == 0)) LY input aka pitch

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)pitch_acc[pdx] = floatFromPIplastAverage = pitch_acc[pdx]

38

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 49: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

++pdxif (pdx gt= numSmoo)

pdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (pdx gt 0)pitch_acc[pdx] = pitch_acc[pdx-1]else pitch_acc[pdx] = plastAverage

++pdx

if (pdx gt= numSmoo) pdx = 0

if ((strcmp(messageFromPI LX) == 0 )) LX input aka roll

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)roll_acc[rdx] = floatFromPIrlastAverage = roll_acc[rdx]

++rdxif (rdx gt= numSmoo)

rdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (rdx gt 0)roll_acc[rdx] = roll_acc[rdx-1]else roll_acc[rdx] = rlastAverage

++rdx

if (rdx gt= numSmoo) rdx = 0

39

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 50: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

if ((strcmp(messageFromPI RX) == 0)) RX input aka yaw

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)yaw_acc[ydx] = floatFromPIylastAverage = yaw_acc[ydx]

++ydxif (ydx gt= numSmoo)

ydx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (ydx gt 0)yaw_acc[ydx] = yaw_acc[ydx-1]else yaw_acc[ydx] = ylastAverage

++ydx

if (ydx gt= numSmoo) ydx = 0

if (strcmp(messageFromPI RTLT) == 0) RTLT aka transversal

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)trans_acc[tdx] = floatFromPItlastAverage = trans_acc[tdx]

++tdxif (tdx gt= numSmoo)

tdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (tdx gt 0)trans_acc[tdx] = trans_acc[tdx-1]

40

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 51: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

else trans_acc[tdx] = tlastAverage

++tdx

if (tdx gt= numSmoo) tdx = 0

if ((strcmp(messageFromPI RB) == 0)) RB input aka vertical

if (floatFromPI gt= -1 ampamp floatFromPI lt= 1)vert_acc[vdx] = floatFromPIvlastAverage = vert_acc[vdx]

++vdxif (vdx gt= numSmoo)

vdx = 0

else if (floatFromPI gt 1 || floatFromPI lt -1)

if (vdx gt 0)vert_acc[vdx] = vert_acc[vdx-1]else vert_acc[vdx] = vlastAverage

++vdx

if (vdx gt= numSmoo) vdx = 0

A4 Arduino Code for Sending Data

41

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 52: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Listing A4 Serial Send to RPiData SendShaya RahmanianDate 20190604 version 2GoalThis code will take whatever value the PIDs are outputtingand send them to the RPi in order to because the RPi controls

rarr directionschange those so that the PID can self adjust THe values are taken

rarr from thePID code being run inside the main program

==================================================int direction_func(float inputSetpoint float inputAngleMPU)

check setpoint and current value from MPU to get directionint dir

if (inputSetpoint gt inputAngleMPU) dir = 1

else if (inputSetpoint lt inputAngleMPU) dir = -1

else dir = 0

return dir

================================================void sendData_func(int inputDirP int inputDirR int inputDirY)

rarr sends the data from the PID to the PI in the form of amppryvrarr n

Serialprint()Serialprint(inputDirP)Serialprint()Serialprint(inputDirR)Serialprint()Serialprint(inputDirY)Serialprint()Serialprint(0)Serialprint(n)

42

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 53: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

A5 Arduino Code for PWM

Listing A5 Arduino PWN code to PinsSteering codeShaya RahmanianDate 20190604 version 2GoalThis code will take the values from the main ROV programand print those to analogwrite with the values determiningthe different movements written here in IF statementsof the ROV The PWM being sent into motordrivers connected toDC-motorsThere is also a WIP smoothing function designed to compensatefor bad values between the RPi and the Arduino

================================================================our acceleration function just takes our different data and

rarr inputs them into our smoothing function and writes therarr correct pin

void pin_func(float pInputAcc float rInputAcc float yInputAccrarr float tInputAcc float vInputAcc)

if(pInputAcc gt= bEWP ampamp rInputAcc lt bEWP ampamp vInputAcc lt bEWP) rarr check if the pitch input is higher than the roll input orrarr vert input

analogWrite(PIN_OUTPUT1 pInputAcc)analogWrite(PIN_OUTPUT2 pInputAcc)analogWrite(PIN_OUTPUT3 pInputAcc)analogWrite(PIN_OUTPUT4 pInputAcc)

else if (pInputAcc lt bEWP ampamp rInputAcc gt= bEWP ampamp vInputAcc lt bEWP)

rarr check if the roll input is higher than the pitch or vertrarr input

analogWrite(PIN_OUTPUT1 rInputAcc)analogWrite(PIN_OUTPUT2 rInputAcc)analogWrite(PIN_OUTPUT3 rInputAcc)analogWrite(PIN_OUTPUT4 rInputAcc)

else if (rInputAcc gt= bEWP ampamp pInputAcc gt= bEWP ampamp vInputAcc lt bEWP

rarr ) superimpose and divide by two if roll input and pitchrarr input is higher than breakpoint value

float averageRP = (rInputAcc + pInputAcc)2

43

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 54: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

analogWrite(PIN_OUTPUT1 averageRP)analogWrite(PIN_OUTPUT2 averageRP)analogWrite(PIN_OUTPUT3 averageRP)analogWrite(PIN_OUTPUT4 averageRP)

else if (vInputAcc gt= bEWP) if vert input is higher than

rarr breakpoint value ignore the restanalogWrite(PIN_OUTPUT1 vInputAcc)analogWrite(PIN_OUTPUT2 vInputAcc)analogWrite(PIN_OUTPUT3 vInputAcc)analogWrite(PIN_OUTPUT4 vInputAcc)

else if nothing happens no valueanalogWrite(PIN_OUTPUT1 0)analogWrite(PIN_OUTPUT2 0)analogWrite(PIN_OUTPUT3 0)analogWrite(PIN_OUTPUT4 0)

if (tInputAcc gt= bEWP ampamp yInputAcc lt bEWP) check if transversalrarr input is higher than yaw input

analogWrite(PIN_OUTPUT5 tInputAcc)analogWrite(PIN_OUTPUT6 tInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc lt bEWP) check if the yaw

rarr input is higher than transversal inputanalogWrite(PIN_OUTPUT5 yInputAcc)analogWrite(PIN_OUTPUT6 yInputAcc)

else if (yInputAcc gt= bEWP ampamp tInputAcc gt= bEWP) if yaw input

rarr and trans input is higher than breakpoint superimpose themfloat averageYT = (yInputAcc + tInputAcc) 2

analogWrite(PIN_OUTPUT5 averageYT)analogWrite(PIN_OUTPUT6 averageYT)

else else set pins to 0analogWrite(PIN_OUTPUT5 0)analogWrite(PIN_OUTPUT6 0)

44

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 55: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

============================================================checks whether the engine is on or not by breakpoints here

rarr returning the statefloat checkstate_func(float inputList[numSmoo] int InputSizeList)

unsigned int smidxfloat arraySumfor (smidx=0 smidxltInputSizeList smidx++)arraySum += inputList[smidx]

float savedAverage = arraySum (smidx + 1)float breakpointcheck = abs(savedAverage)

return savedAverage===============================================================smoothing function which removes bad values and smoothes out the

rarr acceleration to avoid jerky movementfloat smoothing_func(float inputState float amplastAverage)

float smoothedAverage

if (inputState = 0)if (lastAverage = 10)smoothedAverage = (inputState + lastAverage)2else smoothedAverage = inputState

else if (lastAverage = 10)smoothedAverage = lastAverage4 else smoothedAverage = 0

lastAverage = smoothedAverage

if (lastAverage lt 01)lastAverage = 0

45

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 56: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

smoothedAverage = abs(smoothedAverage) 100return smoothedAverage lastAverage

46

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 57: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Appendix B

B1 Electrical Circuit

Figure B1 The electrical circuit inside the ROV Made with [6]

47

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 58: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

Bibliography

[1] Gianluca Antonelli Underwater Robots eng 4th ed 2018 Springer Tracts inAdvanced Robotics 123 2018 isbn 3-319-77899-4

[2] Arduino Uno Rev3 httpsstorearduinoccarduino-uno-rev3 Ac-cessed on 2019-05-05

[3] FA Azis et al ldquoProblem identification for underwater remotely operated ve-hicle (ROV) A case studyrdquo In Procedia Engineering 41 (2012) pp 554ndash560

[4] Brett Beauregard Improving the Beginnerrsquos Pid httpbrettbeauregardcomblog201104improving-the-beginners-pid-introduction Ac-cessed on 2019-05-05

[5] BSS138 N-Channel Logic Level Transistor httpswwwelectrokitcomuploadsproductfile41014BSS138pdf Accessed on 2019-05-05

[6] Circuit diagram editor https www circuit - diagram org editorAccessed on 2019-06-04

[7] Jean-Jaques E Slotine Dana R Yeorger John G Cooke ldquoThe Influence ofThruster Dynamics on Underwater Vehicle Behavior and Their IncorporationInto Control System Designrdquo In JOURNAL OF OCEANIC ENGINEERING15 NO3 (1990) pp 167ndash178

[8] DC-Motor 6v 250mA 14500 rpm httpswwwelectrokitcomproduktdc-motor-6v-250ma-14500rpm Accessed on 2019-05-05

[9] Image of XBOX controller httpsgdimage-gmktcomCOMPATIBLE-WIRED-XBOX-360-CONTROLLER-FOR-COMPUTER-AND-XBOX-360li497618711618497g_400-w_gjpg Accessed on 2019-05-28

[10] L298 H-bridge httpswwwelectrokitcomuploadsproductfile41016L298_H_Bridgepdf Accessed on 2019-05-05

[11] MPU-6050 Inertial Measurement Unit httpswwwinvensensecomproductsmotion-tracking6-axismpu-6050 Accessed on 2019-05-05

[12] PP-Pipes from Jula httpswwwjulasecatalogbygg- och- fargvatten-och-sanitetavloppavloppsror-och-tillbehorror-451389Accessed on 2019-05-28

49

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 59: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

[13] Raspberry Pi 3 Model A+ httpswwwraspberrypiorgproductsraspberry-pi-3-model-a-plus Accessed on 2019-05-05

[14] Raspberry Pi Camera Module v2 httpswwwraspberrypiorgproductscamera-module-v2 Accessed on 2019-05-05

[15] Ian C Rust and H Harry Asada ldquoThe Eyeball ROV Design and Control ofa Spherical Underwater Vehicle Steered by an Internal Eccentric Massrdquo In2011 IEEE International Conference on Robotics and Automation -ShanghaiInternational Conference Center (2011)

[16] USGS - United States Geological Survey Water Density httpswwwusgsgovspecial-topicwater-science-schoolsciencewater-densityqt-science_center_objects=1qt-science_center_objects Accessedon 2019-05-05

50

TRITA TRITA-ITM-EX 201959

wwwkthse

Page 60: Sharkbait - a self-stabilising underwater drone Sharkbait ...kth.diva-portal.org/smash/get/diva2:1373541/FULLTEXT01.pdf · Mechatronics, Drone, Underwater, Self-stabilisation. Referat

TRITA TRITA-ITM-EX 201959

wwwkthse