From CUSF Wiki
Revision as of 18:57, 19 April 2021 by TimClifford (talk | contribs) ("Add old wiki")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Project Kestrel

Goal: Develop a stabilisation system for model rockets so they will always fly straight.

Original plan of action:

  1. Develop a flight computer which will log relevant data.
  2. Build a payload rocket for the flight computer.
  3. Use flight computer to collect data from model rocket launches.
  4. Use the data to design appropriate control surfaces.
  5. Build a rocket with control surfaces operated by 4 servos.
  6. Test rocket in test rig to check it works as expect, including measuring off axis thrust.
  7. Launch the rocket.

Control surfaces: Several possible options:

  • Exhaust fins
  • Exhaust tabs
  • Air steam fins

Exhaust fins were used on the V2 300px

Jet Tabs used on tomahawk missile 300px

Flight computer: I am using an Arduino Uno. With these sensors:

  • ADXL345 3 axis accelerometer
  • PS-ITG-3200 3 axis gyro
  • HMC5883L 3 axis magnetometer
  • BST-BMP085 Barometer

and an SD card reader.

Everything on the breadboard


Soldered together


The next task was to build the hardware. It was decided to try a gimbaled motor approach, which would be actuated by 3 servos (Power HD High-Speed Digital Sub-Micro Servo DSP33) positioned radially near the end of the motor. The only small motor with a relatively long burn time (3 seconds) which we could get from Rockets and Things was an Aerotech F22J.

Gimbal parts


3D printed servo mounting ring


View of the servo arrangment


The rocket was quite heavy (1kg) which would result in about 1 g of acceleration. The parachute lives in the top white section, a black powder charge at the base of the top section ejects the nose cone and with it the chute. The top section is held to the lower section by 4 radial screws. In the lower section lives the flight computer and below that the gimbal arrangement.


In hindsight this arrangement had a number of annoying flaws:

  • Using 3 servos results in a indeterminate system.
  • The servos protrude into the air stream, not good for efficient rocket design.
  • Neither the micro SD card or the USB socket on the arduino could be accessed once the computer was in the rocket.

For the next version I would use a different gimbal design which would allow 2 servos to be mounted above it.

The flight computer required an addition circuit to ignite the ejection charge. This was simply a mosfet controlled by a digital pin which when opened would discharge a capacitor through the E-match. Some resistors featured to limit current flow. The flight computer now looked quite cramped.


The next major element was how should the control software operate. The basic principle is to integrate the angular velocities from the 3 axis gyroscope, then feed this information through a PID loop to move the servos. As 3D rotations are non commutative they can not be integrated separately. After several headaches the approach which made the most sense used matrices. The method is referred to as the "Direct Cosine Matrix" by people who use it for drones. Search google for DCM draft for an explanation of how it works. The orientation of the rocket is represented by a 3x3 matrix which describes the transformation between the ground coordinate system and the rocket coordinate system. To update the matrix you multiple it by a matrix calculated from the angular velocities multiplied by the time interval. It is the equivalent of adding a small rotation. I recall finding out that a vector cross product can be written as a matrix multiplication which helped understanding at some point.

As far as I'm concerned the accelerometer is of no use in determining attitude as you can't differentiate between the acceleration form the motor and that from gravity. By using the accelerometer to detect launch the gyro drift becomes insignificant over the 3 seconds of flight. It is required to renormalise the rotation matrix during the integration otherwise due to errors the matrix will blow up.

The next trick is to get something to feed into the PID controller, or as it turned out the 2 PIDs, one for yaw and one for pitch. It is worth noting that the convention I used for pitch, yaw and roll is not the standard as I wasn't aware of the standard when starting. For a second version I would adopt the standard, which is: to use a right-hand coordinate system for rockets where the long axis (nozzle to nosecone, your "vertical") is X with +ve toward the nose. So your "horizontal" axes are Y and Z.

As it turns out all that needs to be fed into the PIDs is the correct elements of the rotation matrix. As we are aiming to fly straight the J vector in the inertial frame is the demanded direction. The rotation matrix transforms a vector from the body frame to the inertial frame (I think this just depends on the sign used on the angular velocities). This means the columns of the matrix are the axis of rocket expressed in the inertial frame. This quickly becomes a mind fuck. If we take the inverse of the rotation matrix (which is conveniently the transpose) the transformation matrix reverses so that it goes from the inertial frame to the body frame. This can be used to convert the upwards vector in the inertial frame (our desired heading is defined in the inertial frame) to the body frame (which is changing).

What we are trying to achieve is to get the upwards vector in the inertial frame expressed in the body frame this gives the components in each of the 3 body axes, the errors are the terms in the 2 horizontal axes. We feed these numbers into their respective PIDs. It is worth noting that there is a small angle approximation here, however if we exceed 45° from the vertical we have bigger problems.

The next challenge is tuning the PIDs. The plan was to use a Simulink simulation of the rocket to do this. Using SimMechanics it was relatively easy to model the rocket as a system, using the Solidworks model to find the inertia matrix. Failing any better ideas I resorted to trial and error for tuning until a robust response was achieved for a variety of disturbances.

The code for the Arduino then had to be written. One problem encountered was the mean spirited nature of SD cards, this meant some of our loops took much longer than others. With some streamlining the code was efficient enough to achieve 100Hz. If something more powerful was used then a solution with ring buffers and multi-threading would be the way to go. I attempted to use time based interrupts but this wasn't compatible with the sensor libraries.

Testing day finally arrived. The first half of the flight was very promising but then instability occurred. I'm yet to determine what caused this. Possible explanations include:

  • Uneven motor burn
  • Too much wind
  • A bug in the software
  • A bug in the simulation
  • Something important neglected in the simulation

The current plan is to repeat the test then perhaps build a model which can be used to verify the simulation in the lab, perhaps using compressed air to provide the thrust.


The Arduino code and the Simulink file are both on Github.

Disclaimer, I'm writing most of this from fairly old memories so there may be errors, the lesson is to document things as you go along.