Individual Project Blog

An exploration of ducted fan thrusters to maneuver mobile robots

The last 7 days have been so busy it almost feels like a month has passed since my last post. The MDF plates were laser cut the day after my last post and since then I've been hard at work, modelling mounts for everything. I know I said in my last post I planned to just zip-tie everything down, but sensors need a fixed reference point without the risk of them moving around within the carriage, and the grid system I designed with zip-ties in mind makes aligning 3D printed mounts for everything relatively simple.

50c14e20-d80f-4ca4-a1c8-3be46e730f6f

With every change I make, I keep the CAD model up to date and as close as I reasonably can to the physical robot. This help me keep everything well-planned and organised and helps me spot any issues before I try printing/assembling anything.

I'm using M3 heat-set inserts to allow my printed parts to be cleanly and securely bolted to the MDF plate through the grid holes.

Another big milestone reached in the last few days is that the track has now been brought up to the lab, a big thanks to Nick, Alex and the other faculty staff who helped move that enormous thing across campus! The next step is integrating the robot with the track!

It's Sensor Time

Now all the hardware is (mostly) attached together, it's time to turn back to the software side of this project. As I began trying to integrate the sensors, I noticed my development environment I had set up a few weeks ago wasn't particularly dev-friendly; intellisense and syntax completion were nowhere to be found. I got to work researching and made some significant improvements to the development experience by introducing Meta's PyreFly language server into the mix and finding sets of Micropython and Pimoroni firmware stubs to get syntax completion and proper import checking for the built-in libraries I'm using (i.e. machine and Inventor. All this is managed as part of the Nix flake, making the whole setup declarative and completely reproducible with a single command on any machine with Nix installed.

With my environment now set up to my liking, I began programming some modules to read the sensors individually (I'll work on combining the data later). The first was the IMU which required a library to be installed. The official bno08x library from AdaFruit is compatible only with Circuitpython, so to use it in Micropython, I found this community-developed library instead. I added it to the nix flake and made it so Nix regenerates the lib folder every time nix develop is run to keep things reproducible. The tutorial documentation is easy to follow and before long I was getting linear acceleration readings from the IMU.

The DFRobot distance sensor is quite a bit more difficult to work with though, it's accessible only over UART by sending raw byte values directly with no library to abstract away the process. On top of that, the documentation leaves a lot to be desired and it heavily implies DFRobot have reverse-engineered this sensor and don't fully know how it works. After a few hours of staring at the documentation and whipping up a quick script to generate the checksums required at the end every command, I eventually got to the point where I could get readings from it and adjust other settings like activating/deactivating the visible targeting laser.

Gantt chart update for this week

e497f046-aadc-4fd5-ab31-7d5a8bc84156

This week was spent designing and assembling the finalised hardware. I made the realisation that placing the fans back to back as in my original quick mock-up would not be the most intelligent way to mount them as the fans would both be obstructing each other. Instead, I have designed the final hardware with this in mind and stacked the fans vertically instead, allowing clear intake and exhaust for both EDFs.

Using my previous static test stand model as a base, I designed the final carriage parts to hold the fans in place. I also added cable management loops to make sure the wires for the upper fan are safely out of the way during operation.

37392516-36d5-4321-b018-39ddadc972bc

The upper part and both fans are held securely in place using an m3 x 100mm bolt, screwed into some brass heat-set inserts in the base of the stand.

44ea6a8f-4a83-4153-a365-0cdc1a541807 The heat-set inserts after just being inserted with a soldering iron

ff7cfc64-146d-41e0-8489-ae04ecc810a5

As with the previous mini test track, I plan to use laser-cut MDF to interface with the rail slider, but the final version of the carriage also needs a place to mount the batteries, sensors and microcontroller. I have designed a system that will use two MDF plates, separated by standoffs with the other components mounted between them.

After modelling the lower plate at a size I thought was sensible, I drew a scale diagram of it on paper and tried arranging the components in different layouts to make sure everything would fit correctly.

02619df9-2a7b-4015-9f70-efb4292adf01

64cd3007-50d4-4ac5-81ed-06b7a2f9a7cd Note the “front” is at the bottom of this image

My initial plan was to 3d print mounts for each individual component and fix them to the MDF plate with screws, but this would mean I would need to decide on a layout in advance without being able to easily switch the positions of components around. To combat this, I instead added a grid of holes to the model of the lower plate so I can zip-tie each of the components in place, along with any wires to keep them secure.

e7cd0253-d959-4a4d-bf9b-7bcee01ed51e

Regarding sensors, I have finalised my decision on the sensors I will be using too. Of course the feedback signal from each fan will be used and alongside it, I have decided on an Adafruit BNO08x 9-DoF IMU which I will use to measure linear acceleration and a DFRobot SEN0366 IR laser distance sensor (ordered, and should arrive early next week). This distance sensor is impressively accurate, at just a 2mm standard deviation between 1 and 5 meters.

I've been in the lab for a good while over the last week, making a lot of progress (although still not as much as I would have ideally liked).

The first big decision I had to make this week was the choice of programming language I was going to use for the microcontroller. The Pimoroni board I'm using has specific libraries and abstractions available through a customised MicroPython firmware, so that looked like the most suitable choice. This is my first time using MicroPython and I'm still a little unsure about the idea of running an interpreted language on a microcontroller. I'm somewhat tempted to try rebuilding what I have so far in Rust to take advantage of its compile-time error checking, but I've only used Rust a tiny amount compared to Python so switching languages may turn out to be shooting myself in the foot and I can't really afford to waste time at this point in the project.

After setting up the development environment, I was able to start programming some tests. The first step was just to get the fan to boot up, which requires sending a PWM signal of 1000 microseconds. I then began translating some of the jerk simulation code to MicroPython to get a smooth but fast ramp-up curve for the thruster. The full git repo can be found here and will continually be updated as the project progresses.

At this point I hit a little bit of choice paralysis, I was unsure whether I should start integrating sensors, work on getting the second thruster working, or start designing the carriage for the track. Alex thankfully broke me out of this and suggested building a small-scale temporary test track so I could begin testing different thrust durations and ramp-up timings to start seeing how these impacted the thruster's movement. Using some laser-cut MDF and a small (approx. 1m long) rail/linear bearing system, I (we! Alex provided the design and laser-cutting expertise) constructed a small-scale test track/carriage system.

ecd00555-37c3-48a7-adaa-d8afd5cad2a1

I mounted the thruster to the carriage plate and checked my code's output without the fan attached to make sure the PWM values seemed sane, despite having done this, the thruster's movement was far too violent, slamming from one end of the track to the other and unplugging itself from the microcontroller (at which point the speed controller's safety cutoff kicked in). I ended up reducing the PWM signal to near minimum and raising it up to about 15% of what I'd tested it at to find a movement that seemed sane.

The next step now is to try figuring out how jerk values actually impact physical movent and begin looking at integrating sensors into the design.

I am writing this blog post from a hotel room so I'll update with pictures as soon as I can.

Over the course of the last week, I have been working on two sub-components of the project; the first is modelling a test stand for the EDF so I can do experiments with the fan safely and securely in place to avoid damage and injury, the second is creating a simulation of the effect of jerk on the theoretical linear position, building on what was explained in my last blog post.

The test stand

I first decided the best way to design the stand would be to model the EDF itself. The Amazon listing for the fan had a diagram giving the physical measurements for parts of the casing which I used to guide the process:

3455b38f-4bb1-4951-bb26-36e0929c2841

I used digital calipers to measure the casing of my own fan as a sanity check and found that some measurements had to be adjusted, and there were parts of the case that did not have measurements shown on the diagram at all, namely the ridge around the middle of the ducting. The final result has all the detail necessary for going on to model the test stand, but I didn't bother modelling unnecessary details like the fan blades.

ed236218-cd8d-46c1-9192-6df3a7af9ec4

Note that I'm using OnShape to do this modelling as it's the tool I'm used to, and having it run in the browser is very convenient for me (especially given that native Linux CAD tools range from fiddly, incomplete mess to non-existent).

Once I had the fan modeled, It was relatively simple to create the main body of the test stand using the fan model as a template and building around it. I used a boolean difference to make the test stand cradle the exact shape of the fan body, including the central ridge, and added two pins to go through the mounting holes to ensure the fan stays in place. The stand also has a large flat portion with a circular indentation so it can be clamped to a table or desk to keep it in place.

ec6c5cf4-a5fd-44b5-9701-320dd366e949

937838ae-f41d-47a6-8066-983778996d34

I printed a test fit to make sure the ridge indent and pins properly fit the real fan by chopping the model down to the bare minimum (a slice around the middle of the stand about 9mm wide) to make sure everything would fit correctly, and then printed the full stand in white PLA+ (it was the spool that happened to be on my printer at the time and I don't have any reason to believe the stand needs any special properties that might require other filaments) at a 0.24mm layer height with 15% cross-hatch pattern infill.

a3332638-0e48-4068-819f-fa10adda7bd6 This is a photo of the fan on the test stand ready to start experimenting.

I did consider adding a way to manage the wires to keep them out of the way, if this is needed, I'll add it on a future revision of the stand, but given it's only temporary, I'm not convinced it will be needed.

Simulation

This simulation is an extension of the spreadsheet I used in my last blog post. I've written it in typescript using the Fresh framework. This is a framework I've used before and I find it allows me to get up and running with less boilerplate than React or Vue, the other popular frameworks I've used and know.

The simulation allows the editing of jerk “keyframes” which function similarly to keyframes in any video editor/animation software, the jerk value changes only when a keyframe is encountered, with each keyframe being assigned a specific “tick” or timestep to which it belongs.

The simulation can then be started, and the green slider at the top will move accordingly, following the position calculated in real time. At the same time graphs for jerk, acceleration, velocity and position are plotted in real time.

3fec24d8-2fb4-4d22-a00d-e538b9bd53f2 It's not pretty but it is certainly functional.

The git repo for this simulation can be found on my labcode here

This simulation helps me to visualise the kind of movements I'll be having to deal with on the actual test track, but the important next step is to be able to find or create an algorithm that can do this process in reverse. Currently, jerk keyframes are the input to the simulation and the final position is the output (with acceleration and velocity being intermediary stages). To accomplish the main goal of this project though, I need to be able to give the algorithm a position along the track and have it calculate the jerk required and when to apply it in order to reach that position.

Gantt Chart

There's not much to add to the Gantt chart this week beyond marking what I've done as complete, although I have added an entry for preparing for the Viva, which should have been on there from the beginning. I'll be conducting experiments this coming week and I'm sure that will lead to “unknown unknowns” becoming “known unknowns” I can add to the chart.

1d9a6180-cc6d-4de9-871f-aa0c92cc9b98

After discussing with Nick and Alex, I came to realise last week's calculations were based on completely flawed logic. I was for some reason under the impression that the thrust of the EDF needed to out-weigh the overall weight of the carriage, which is not true when moving horizontally (no force of gravity to overcome).

This means that the EDFs I ordered are definitely overkill for what I need them for, but they have already arrived (several days earlier than expected) and returning them and waiting for less powerful fans would just be a waste of time at this point.

To make everything work, I need to calculate the force required to move the entire carriage using Newton's second law of motion, F=ma.

  • m is the mass of the carriage, which will be static once it's built
  • a is the acceleration which will be variable depending on the position the carriage needs to reach
  • F is the thrust required (in Newtons) to make the carriage move at the specified acceleration

The forces involved with EDFs can be very high, high enough to damage or break the motor in some cases. It is important to make sure the acceleration does jump from 0 to 100% too quickly. This means I need to be looking at the next differential up from acceleration, jerk.

Jerk is the rate of change of acceleration, in a similar way to how acceleration is the rate of change of velocity. By making small adjustments to jerk, even just between discrete values of 1, 0 and -1, it's possible to finely and smoothly adjust acceleration in a way which ensures the forces applied to the motor shaft aren't going to do any damage.

This graph shows a simulated change in jerk, acceleration, velocity and absolute position over a span of 200 discrete time steps:

2b3b2a14-b94c-40d9-bee2-ebc439214ef5

Note that velocity and distance have been scaled to 1/10 and 1/100 of their true values respectively, in order to make the other elements of the graph properly visible.

Over the next couple of days, I will work on creating a dynamic visual simulation. This will help me visualise the equations I need to implement for the real hardware.

My updated Gantt chart for this week: 8e5755e6-83e6-43b3-b3ce-92eaeaac4c67

I have spent some time over the last week proving beyond a reasonable doubt that the parts are the correct ones for the job.

Using the specs for ducted fans shown on the Amazon listing, I have created a spreadsheet to calculate the costs and capabilities for each of several ducted fans available in the range of a supplier.

fa0874da-8ec8-4d58-bebd-2d4518536e3c

The above table shows the specs of the various EDFs in the range, and calculated remaining thrust capability (thrust remaining after the entire carriage weight is taken into account) and the unit thrust per £GBP.

The total carriage weight is calculated as:

2*(EDF weight+Recommended ESC Weight) + Recommended Battery Pack Weight + 500

With the final added 500g to account for the microcontroller, sensors, 3d printed chassis etc.

The table determines that the 3S 50mm and 3S 64mm EDFs are not adequate as the thrust produced by these models is less than the total carriage weight would be if these fans were used, meaning the carriage would be unable to move, even theoretically. The 4S 50mm does rise above this threshold, but only very slightly (by 40g) and these calculations do not account for air resistance, track friction or inefficiencies in the motor. It is therefore unlikely that this EDF will be fit for purpose.

The sensible options seem to be to either stick with the 4S 70mm for a 90% higher remaining capability and a 63% higher remaining thrust capability per £GBP, or downgrade to the 4S 64mm to save £15 total and potentially increase battery life by up to 44% (assuming constant peak power draw).

You will see I have also added the next highest model, the 6S 70mm to the table for completeness, but this model's power consumption is far greater than that of any of the “lower tier” models. Because of this it requires a much heaver and more expensive battery pack and does not provide a clear warranted use case.

I have decided that the higher remaining capability of the 4S 70mm will provide a greater thrust window with which to experiment and is therefore worth the price. I have ordered one with which to begin testing.

Unfortunately, the delivery time from this supplier is 8-14 days and I could not find any other suppliers selling EDFs with similar specifications in a more suitable timeframe. I may have to order a smaller and less capable EDF and ESC if I can find one with a quick delivery window in order to get some experience writing code to interface with the ESCs and control the EDFs.

The same ducted fan model I mentioned in my post on 1st July is also sold in a bundle with an appropriate 80A ESC (Electronic Speed Controller). As far as I can tell, this makes it around £2-10 cheaper than buying an equivalent ESC separately (just going by amazon listings at time of writing) and ensures correct compatibility with the EDF.

The product listing shows a wiring diagram, including connecting the ESC to wired and wireless control systems. I'll need to look into how to connect the ESC to an Arduino or similar microcontroller so I can control the thrust output using my own code.

bea268e6-4a9b-4d14-8437-d8bac5d89b61

I will also need a battery, helpfully the listing for the fan and ESC lists an appropriate compatible LiPo battery model: “4S 3500MAH 35C”.

Some preliminary research has revealed that this means the appropriate battery pack will need to have 4 cells in series (to produce the appropriate voltage) and a safe continuous discharge rate of at least 35 times its theoretical capacity of 3500mAh (around 122.5A).

If the battery in question was to be discharged at that rate continuously, it would only last around 1 minute and 45 secoands before running flat. It is probably sensible to purchase at least two battery packs so I can continue working while one charges.

Searching that model on amazon shows battery packs with voltages listed as 14.8 volts. This is what is considered the nominal voltage for the battery pack, but when fully charged, the pack can output as much as 16.8 volts, the amount listed as the maximum for the EDF.

The principle is shown in the following graph from a dataset collected by Matteo Galeotti et al. and published in science direct. It shows the voltage curve for a similar single lithium polymer cell while discharging:

It shows the voltage output starting high at around 4 volts before sharply dropping off and then following a shallower curve (around the nominal voltage) before dropping off steeply again as it finishes discharging. This graph also shows the change in that voltage curve over a number of charge-discharge cycles, but i don't expect that to be of significant concern over the short period of time I will be conducting my experiments.

Of the listings shown on Amazon, almost all of them come in bundles of 2 packs. All these listings range from around £50-60. This listing has appropriate battery packs available for £52.43 for a bundle of 2.

This should be enough parts to build an initial test assembly and begin experimenting with writing code to control the EDF's thrust output. I'll need to purchase a second EDF and ESC in order to construct the carriage for the 1D linear test track setup I proposed in my previous post on 4th July.

I have put together an initial BOM which I will send via email to request the uni purchase the required parts: 4817a283-77cb-4bed-868e-ce1753be18a6

I have also updated my Gantt chart, and I'll start including the most recent version at the end of my blog posts going forward: b4eff7ae-67a6-42ce-9dde-dc527d6a2858

I've drawn up a very rough diagram for what my initial test track concept may look like:

test track blueprint image

My concept involves a track made from aluminium extrusion and a carriage with forward and rear-facing ducted fan thrusters. The aim is to configure the trust output so that the alignment arrow stops in line with various marked goal positions accurately and in a reproducible manner.

Sensors (such as a laser range finder) will be added at a later time and the controller programmed to dynamically calculate the required thrust control, once I have developed an understanding of the thrust characteristics and implemented an algorithm capable of reaching hard-coded points.

Many consumer off-the-shelf electric ducted fan modules exist for use in hobbyist aircraft and similar projects. These come in various common formfactors: 50mm, 70mm, 90mm, 105mm and 120mm.

These modules consist of a brushless motor, propeller/impeller and an enclosure, and are pre-balenced for safety and efficiency at high rates of rotation. Being designed for model aircraft, they are often made from lightweight materials such as carbon fibre, nylon and fibreglass.

Module prices vary from less than £20 all the way to £300 or more for premium models, with the above module being £33.00 at time of writing.

These modules produce varying amounts of thrust, with larger diameters capable of producing higher amounts. This 70mm module has a thrust rating of 1.810kg thrust-equivalent (17.75N)

They are often controlled by connecting them to a standard Electronic Speed Controller (ESC) that allows the speed of the motor and therefore the thrust output to be adjusted. As part of my project, I will need to calculate how adjusting the speed of the motor impacts the thrust produced and then work out how to use those calculations to automatically produce the desired movements.

My current search methodology to find this existing research is to search Goolgle Scholar using search terms such as “electric ducted fan thrust vector control”

Much of the existing research into ducted fans is targeted at drones, UAVs and experimental electric aircraft.

Here are some papers I found that seemed the most relevant to my exploration into ducted fan thrust vecotr control systems for use in robotics:

Design and Full-Pose Control of a Ducted Fan Aerial Robot with Dual-Axis Gimbaled Thrust-Vectoring Mechanisms describes an aerial robot with gimbaled ducted fans instead of classic rotors to create a 6DoF thrust vector control system. The paper describes the use of “Lyapunov-based control” which looks complex and may be beyond the scope of my 12 week project, from my current understanding this refers to a mechanism used to find a stable point that may only be relevant to flying craft/robots (although this video by Professor Giordano Scarciotti on YouTube does provide a seemingly good visualisation that I may return to if understanding of this becomes relevant to me).

Experimental Investigation and Performance Evaluation of an Electric Ducted Fan (EDF) for Distributed Propulsion Systems Looks like it may be relevent to me as it mentions the building of a test rig “was used to characterize the relationships between the Pulse Width Modulation (PWM) control input and the primary performance outputs, including fan rotational speed (RPM), static thrust, and electrical power consumption.” However, I only have access to the abstract for this paper, I'll need to check with the university to see if I can get access to it.

# Development of a One Axis Thrust Vectoring Control System Demonstrator with Electric Ducted Fan Seems like a good candidate to be looked into more deeply, this paper describes a single degree of freedom test rig for a ducted fan system being used to model thrust vector control for spacecraft in an atmospheric environment. The test rig described in this paper specifically tests the pitch rotational axis, somewhat different to the initial idea I have in mind for a linear test rig

SkateDuct: Utilizing Vector Thrust of Ducted Fan UAVs for Terrestrial-Aerial Locomotion Seemingkly describes a turtlebot-like robot that uses a ducted fan for short flight capabilities, enabling it to hop over small obstacles. Interestingly, directed air currents from the single ducted fan are also used for ground-based propulsion/locomotion.

Other notable things

Jet-HR2: A Flying Bipedal Robot Based on Thrust Vector Control Describes the use of a ducted fan to enhance the capabilities of a disaster response robot, allowing it to perform long or high jumps. This probably isn't all that relevant to my research but it is cool