ArdIU - Open source flight computer w/ ATMega328

The Rocketry Forum

Help Support The Rocketry Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
The fun is that I've left the IMU on a table for an hour and got sub-degree drift...

Sent from my LGL44VL using Tapatalk
 
The fun is that I've left the IMU on a table for an hour and got sub-degree drift...

Sent from my LGL44VL using Tapatalk

Turn off the accelerometer drift compensation (which you can't use in a rocket) and see what drift you get.
 
Turn off the accelerometer drift compensation (which you can't use in a rocket) and see what drift you get.

John is right - I think a lot of the sensor fusion algorithms assume a gaming or vehicle environment where you have a relatively stable 1G reference. This is completely out the window for rocketry. I'm working on a sensor fusion between the gyro and magnetometer right now, but for tilt-lockout its really not necessary.

Think about it - if your drift is a few degrees per hour, or even per minute, then the gyro will still be very accurate within the few seconds between liftoff and 2nd stage ignition. Anything beyond that and all you're doing is figuring out the orientation at apogee - much less useful.

I welcome dissenting opinions - I frequently demonstrate my ignorance on these forums.
 
Think about it - if your drift is a few degrees per hour, or even per minute, then the gyro will still be very accurate within the few seconds between liftoff and 2nd stage ignition. Anything beyond that and all you're doing is figuring out the orientation at apogee - much less useful.

The gyros have unknown cross axis and acceleration sensitivity. How big of a problem is that? Unknown pretty much covers it. Although Jim Jarvis had trouble which pushed him to a spinning fin can.

Drift is the least of your problems.
 
The gyros have unknown cross axis and acceleration sensitivity. How big of a problem is that? Unknown pretty much covers it. Although Jim Jarvis had trouble which pushed him to a spinning fin can.

Drift is the least of your problems.

Great points and well taken. I've looked into the cross-axis / acceleration sensitivity over the past 2 years and decided its not that bad. I have only used the L3GD20H so I can't say anything about other units.

In those 50 some odd flights, I can definitely say that the gyro is good enough for tilt-lockout. I developed my own non-quaternion algorithm that's a take off of the 2D DCM method. Comparing the estimate to the onboard video shows that there is typically about a 3-8 degree difference after about 20 seconds of flight. There definitely is some oscillation in the off-vertical estimate, but I can't tell if its because of the algorithm or the gyro. I recently figured out quaternions, so I'll go back in the data to try and separate the two. I've also found that proper calibration of the gyro makes a stunning improvement in the accuracy.

Estimating orientation for attitude correction like Jim Jarvis is a whole different ballgame. Eventually I may get there, but I need a few flights with quaternions to estimate how well it works. The L3GD20H is a few years old now, and the LSM9DS1 is the latest/greatest, so that might be my next step.

I always appreciate input from the pros. I do this for a hobby, not a living, so I often don't have the required base knowledge.
 
Last edited:
Question: Have any of you guys ever worked with an IMU from Pesky Products called the Ultimate Sensor Fusion (Link)? I am considering using it for my Teensy project.
 
Here is a brief summary of my understanding as to how the maths works with the accelerometers and gyros. If you assume a relatively static 1G accel these 3D devices can provide pretty good accuracy and little drift, once corrected mathematically. The vector sum of the three axes adds to 1G if you average it over a relatively small amount of time. The firmware in these IMU units always tries to mathematically keep a reference frame of where the device is in space, with the three axes of the accelerometers at right-angles (orthogonal) to each other, and with the same scaling. Think of a cube, where three sides meet at a corner for X, Y, Z (or yaw, pitch, roll). It uses the accelerometers and gyros to "rotate" this around in space to give a representation of the attitude of the vehicle. Gyro or accelerometer drift effectively distort the cube, perhaps stretching or shrinking it in one or more directions, or pushing the cube such that the sides are not orthogonal any more (think sort of parallelogram-shaped). The 1G reference field for the accelerometers is used to correct for any distortions in the reference frame mathematics to keep it orthogonal and correctly scaled.

The problem with rocketry is that the vehicle is not in a 1G static field. Gyros and accelerometers can end up pegged by boost accelerations and jolts, and the drag on a freshly boosted but burnt-out rocket effectively turns the G-field upside down for a while, even while flying vertical. The relatively long-term average is also a lot more than 1G under boost. Any algorithms attempting to correct for drift in the flight computers need to take into account the peculiar environment a rocket creates and tune the reference frame at times when the inputs are sensible. Before takeoff is a good time for that. After that any chance of correcting can probably be forgotten about. Since the flights are relatively short this mostly does not matter anyway.

The moral of the story is to parse any input data for sensibility before using it, so that something off-nominal has less of a chance of negatively affecting the performance of the flight computer. Good programmers will do this. Hobbyists and fresh graduates sometimes forget, with strange results from corner-cases in the code appearing as "glitches" in behaviour.

The devil is in the detail :)
 
Great points and well taken. I've looked into the cross-axis / acceleration sensitivity over the past 2 years and decided its not that bad. I have only used the L3GD20H so I can't say anything about other units.

I am using the L3GD20H and I find it excellent. I tried to determine acceleration sensitivity but putting it on shaker table and reading the output and it appears relatively insensitive. My next step is to spin one about an axis and see what the magnitude of cross-axis sensitivity is. I want to do that wirelessly somehow so I don't have to figure out how to wind up the wires.
 
One of the things that we have done is to change the method used to account for gyro offset and to optimize the rate at which the process occurs. Basically, the offsets are calculated while the rocket is on the pad, rather than at some point prior to launch (which is what we do for the accelerometers). The speed of this process has been adjusted such that it takes about 10 minutes to drive the error to zero, so we need to wait for that amount of time before launch. This slow response also makes the process immune to rocket movement due to the wind, or while raising the rocket, or due to the initial movement of the rocket (before the launch detect algorithm is able to shut off the accelerometers).

Jim
 
Thanks for the ideas all!

I'm considering just using the difference between the angle at burnout and the angle at liftoff detection as my tilt lockout standard. I'd just store non-rotated orientations and let the secondary data-processing figure out the rest for post-flight analysis. It depends exactly how it's calculated, but I'm guessing that gravity based corrections won't be an option- however, if the IMU only corrects when close to 1G for awhile then it might work. I'll have to research that.

However, from the discussion I'm hearing it sounds like nobody has any issues with the hardware, so the fabled time of ordering PCBs is drawing closer. I did find time to lay out all the components, though not to route the PCB yet. I'm going with an Amphenol microSD slot that looks pretty solderable (1.25mm pitch, real leads not LGA, and nothing is "underneath") and 3.3V logic w/ the ATMega internal 8MHz clock. The nice thing about the standalone slot is I got the board length down to 3.25" from the original 4". (Width is still 1.3" or so.) Otherwise, everything is the same.

I'm still looking for beta testers! So far I have bandman444 and Tobor as interested.

Adding to the SD card debate, the Arduino SD library unfortunately doesn't support plain old ints & floats. It does allow byte arrays though, and I should (hopefully) be able to write up a basic function to "split" an int, float, etc. into its constituent bytes. Seems like kind of a pain though... Ah well, 'tis the price you pay for decent write times.

I can't reiterate enough- thank you, everyone who has contributed! As soon as I have a few minutes to spare, the ArdIU library will start including all of these great ideas... So far, it can basically read the battery voltage...
 
I'm considering just using the difference between the angle at burnout and the angle at liftoff detection as my tilt lockout standard. I'd just store non-rotated orientations and let the secondary data-processing figure out the rest for post-flight analysis. It depends exactly how it's calculated, but I'm guessing that gravity based corrections won't be an option- however, if the IMU only corrects when close to 1G for awhile then it might work. I'll have to research that.

It only works while you are on the ground. Or once it is hanging under a parachute.

Adding to the SD card debate, the Arduino SD library unfortunately doesn't support plain old ints & floats. It does allow byte arrays though, and I should (hopefully) be able to write up a basic function to "split" an int, float, etc. into its constituent bytes. Seems like kind of a pain though... Ah well, 'tis the price you pay for decent write times.
Create several 512 byte arrays. Store your data there and call the SD library to write the data when you have a full 512 byte buffer.

No need to break the data apart. All you need is some pointer magic:

Code:
     char *bufp;
     int data;

     *((int *)bufp) = data;
     bufp += sizeof(int);

This converts the character pointing into an integer pointer and then uses the pointer to store the data. On some architectures you have to worry about alignment but I don't think yours is one of them.
 
I am using the L3GD20H and I find it excellent. I tried to determine acceleration sensitivity but putting it on shaker table and reading the output and it appears relatively insensitive. My next step is to spin one about an axis and see what the magnitude of cross-axis sensitivity is. I want to do that wirelessly somehow so I don't have to figure out how to wind up the wires.

I have found the same thing. In all my flights I see little to no correlation between the gyro outputs and the accelerometer values. I can't say for cross-axis sensitivity, I honestly think that there is some, but it doesn't impact the calculations that bad.

Last night I went and calculated the quaternion rotation for one of my previous flights. See the attached photo. I was quite stunned as to how close the 2D-DCM and quaternion estimates are. The 2D-DCM only requires 6 floating point operations, is an order of magnitude faster (maybe two), and can easily be implemented on a ATMega328P. Quaternions are much more computationally intense and require lots of floating point math.

Its also worth noting that only the magnetometer captured the fact that it rotated 90 degrees at apogee. As Jim Jarvis alluded, my primary suspect is the gyro calibration. I had a very simple routine for this flight that I have since improved. I don't want to do 10 minutes like Jim, but a few seconds should be able to get me close enough for my purposes.

Algorithm Comparison.jpg
 
The 2D-DCM only requires 6 floating point operations, is an order of magnitude faster (maybe two), and can easily be implemented on a ATMega328P. Quaternions are much more computationally intense and require lots of floating point math.

Curious how are you using just a 2D - DCM? Are you ignoring the roll (spin) axis?

I am using quaternions because it has fewer computations and faster than a 3D DCM. However I implementing that on a ARM in integer math.
 
Curious how are you using just a 2D - DCM? Are you ignoring the roll (spin) axis?

I am using quaternions because it has fewer computations and faster than a 3D DCM. However I implementing that on a ARM in integer math.

Thats awesome - I'd love to figure out how to quaternions with integer math.

As for 2D-DCM, I completely stumbled onto it and I'm not totally sure why it works. Here's what I'm doing each cycle, where Z is the vertical axis, and X & Y are parallel to the deck:

Roll += gyroZ * dt
Pitch += gyroY * dt * cos(Roll) + gyroX * dt * sin(Roll)
Yaw += gyroY * dt * sin(Roll) - gyroX * dt * cos(Roll)

I then combine pitch and yaw to come up with the off-vertical estimate:

Off-Vertical = atan(sqrt(tan(Pitch)^2 + tan(Yaw)^2))

I optimize the equations for speed and efficiency using a bunch of simplifications and trig identities, but the above is basically what I'm doing. I've tested it extensively and found that if you swing the unit around wildly, it quickly loses accuracy. However, if you spin it like a top around the vertical axis (like a rocket spinning in flight), and then you make a rotation in any direction, it will be accurate as long as the rotation is in a single 2-D plane. In other words, its accurate if the rotations mimic a ballistic trajectory - which accurately describes nearly all rocket flights up until apogee.

These equations are great for tilt-lockout of 2-stage flights and will catch an unsafe attitude every time. They also are fast on an ATMega328P and require very little flash/RAM.
I'm working with two other NAR/TRA members who are using the equations above and they have also had good results.

I recently improved my calibration routine, and it has helped a lot. My recent flights have nailed the angle-off-vertical all the way to apogee. Below is video from my most recent flight. At apogee the 2D-DCM estimated 90 degrees off vertical, and the camera shows that the rocket is pointed directly at the horizon at apogee.

[YOUTUBE]FstkvJmWx38[/YOUTUBE]
 
Last edited:
Thats awesome - I'd love to figure out how to quaternions with integer math.

As for 2D-DCM, I completely stumbled onto it and I'm not totally sure why it works. Here's what I'm doing each cycle, where Z is the vertical axis, and X & Y are parallel to the deck:

Roll += gyroZ * dt
Pitch += gyroY * dt * cos(Roll) + gyroX * dt * sin(Roll)
Yaw += gyroY * dt * sin(Roll) - gyroX * dt * cos(Roll)

Veryi interesting. I wonder if you have tested that with a rocket that has a high roll rate while it has a high yaw and pitch rate?

If the roll rate is low then the small angle assumptions reduces your equations to:
Roll = gz*dt
Pitch = gy*dt
Yaw = gx*dt
which is simply integrating the Euler angles for each time step. The math says to calculate the rotation of the body vector relative to the earth vector you need to multiply the 3x3 DCM matrix. If you have no roll then this is not necessary and you can simply integrate the yaw and pitch rates.

On your video you had practically zero roll at apogee and during ascent while you were rolling a little you had very little pitch and yaw. Which is why I asked earlier do you have any flight data with decent amount of roll along with a pitching/yawing rocket? Especially interesting would be if you have a test flight where the rocket was spinning through apogee and see if you got the 90 degree turn accurately?
 
Veryi interesting. I wonder if you have tested that with a rocket that has a high roll rate while it has a high yaw and pitch rate?

If the roll rate is low then the small angle assumptions reduces your equations to:
Roll = gz*dt
Pitch = gy*dt
Yaw = gx*dt
which is simply integrating the Euler angles for each time step.

Yes, you are correct that if there's no roll, then my equations break down to what you have above. I look at that too, and call it "naive yaw" and "naive pitch" in my graphs.

Here's one with a high roll rate that still accurately captures the off-vertical at apogee. You'll have to take my word for it because I haven't posted the onboard video.

I do notice more error on the higher roll flights, but its not consistent. Some flights are dead-on, some 30 degrees off at apogee. In either case, its still useful for 2-stage tilt-lockout. In my 50+ flights, it always captures large moves away from vertical. I set my lockout threshold to 35 degrees and have had no trouble.

Rotation Estimate 14 April.jpg
 
Yes, you are correct that if there's no roll, then my equations break down to what you have above. I look at that too, and call it "naive yaw" and "naive pitch" in my graphs.

Here's one with a high roll rate that still accurately captures the off-vertical at apogee. You'll have to take my word for it because I haven't posted the onboard video.

I do notice more error on the higher roll flights, but its not consistent. Some flights are dead-on, some 30 degrees off at apogee. In either case, its still useful for 2-stage tilt-lockout. In my 50+ flights, it always captures large moves away from vertical. I set my lockout threshold to 35 degrees and have had no trouble.

Ok, i don't want to hijack this thread. If you want we can continue in another thread or not if you are happy. I am just trying to understand for myself why an approach that shouldn't work on paper is working for you.. :)
 
So I got the prototype altimeter assembled over the last few days. Came out pretty nice:
View attachment 336702View attachment 336703

I first built it without breakout boards and tested it, then added the boards afterward, just in case I needed to fix something.

My comments:
- Several footprints were mis-sized, most significantly the SD breakout. I can work around it but it's annoying enough that I'm going to want new footprints for the first beta run.
- The polarity on the LEDs was very hard to see. I was using Sparkfun's library for these- I'll switch to the Adafruit footprint, which is much clearer, in the future.
- Most of the info text on the back was practically invisible. Easy fix.
- The programming header was set up backwards. I can work around it by just flipping the programmer, it's just not ideal.
- I'm planning on running the entire board at 3.3V with internal clock on the next iteration. I found a high-efficiency version of the 1117 that can run 3.3V off of as little as a 2.5V input, so I can run 1S LiPos- I have quite a few lying around.
- I'm also planning on moving the SD card from a breakout board to a standalone holder. I just need to find one that's reasonable to solder...
- Several bugs in the Arduino library have been worked out- mostly related to the annoying way C handles floats- float x = 1/2 will give zero because the 1/2 part is reading as an int. float x = 1.0/2 fixes it. Still have a lot more to go there.

Two quick polls-

How much interest is there in a beta run once all of these issues are taken care of? OSH Park sells boards by 3's so I'm planning on getting 6- one for myself and if that goes well 5 beta kits. Beta kit price would probably be around $30-40, and gain you my undying gratitude, your name/handle on the production board, and first pick at debugging help and/or code customization, plus maybe more stuff.

For datalogging, which would be more useful by default- CSV or TSV? I can make it configurable, I'd just be interested to know what people prefer.

Thanks for all the interest!

Sounds very cool [emoji41]


Sent from my iPhone using Rocketry Forum
 
Ok, i don't want to hijack this thread. If you want we can continue in another thread or not if you are happy. I am just trying to understand for myself why an approach that shouldn't work on paper is working for you.. :)

I agree, I'll PM you offline. I debated the same thing, but the equations are relevant to what the author is trying to do.
 
Don't worry about it! I'm planning on implementing this exact type of thing, so the discussion is relevant... Plus it's interesting! Go ahead!
 
I compared this code:

Code:
      pitch += gy * dT;
      yaw += gz * dT;
      pitch += yaw * gx * dT;
      yaw -= pitch * gx * dT;

based on yet another thread to my quaternion version and they stayed the same up till apogee. There was a significant difference afterward but that might have been due to the way that I combined pitch and yaw into tilt.

On an ARM with floating point hardware this can all be done using floats at high speed. On an 8 bit machine you want to avoid floats if you have any desire at all for high speeds.

Note that I use the small angle approximation here which means that you must keep the sample rate up so that the maximum roll angle doesn't invalidate that approximation. Otherwise you get to invoke the slow sin/cos library.

More speed can be had by using fixed point since the high dynamic range of float is wasted here. If you also choose a sample rate that is a power of two then you can change the "* dT" to a shift for even more speed. This is difficult since most of the sensors cannot provide suitable sample rates. But some of the MPU parts will accept an external 32768Hz reference which makes it possible.

While gx must be converted to radians (because of that small angle approximation thing) there is no need to do that for pitch and yaw. In a summation a multiplication by a constant inside the summation as is done here is the same as a multiplication done outside. So that conversion can be delayed or even eliminated.

Since this is presumably being done for use in a tilt lockout, just adjust the threshold.

One hassle in using fixed point with C is that C doesn't provide a suitable multiply. What you want is something that multiplies two 32 bit numbers together and returns a 64 bit result. Instead you get 32. This requires that you convert your 32 bit ints into 64 bit ints so you get a 64X64 multiply which is a lot slower.
 
If you also choose a sample rate that is a power of two then you can change the "* dT" to a shift for even more speed. This is difficult since most of the sensors cannot provide suitable sample rates.

Isn't the sample rate calculation arbitrary and correctable later? If your real sample rate wants dT to be 10 but you use shifts and calculate based on 8, all your rotations will be scaled by 10/8. You then can correct for with a single multiply correction at the end of the calculation string or just once on your target value if tilt lockout is the mission.
 
Found an error in my algorithm comparisons. Here are two flights with very different roll profiles. Quaternion and 2D-DCM estimates virtually match each other. Makes me think that cross-axis sensitivity is the likely culprit for the oscillation seen in the first one - it spun like a top on the way up. I can probably go back in all my data and use simple linear regression to characterize the cross-axis spillover. Then I could account for it on future flights.

Algorithm Comparison.jpgAlgorithm Comparison2.jpg
 
I commented on roll during control in Jim's thread earlier (15FEB2017). Here is the quote verbatim to save me writing it again:
Yep. Need to stop the roll first. Otherwise it ends up like the rotor dynamics of a helicopter. The rotation of the main rotor causes a shift in the phase of the applied moment from the fins. Helicopters can be almost 90deg out of phase with the position of the blades relative to the required force moment. For example, you need to apply the required AoA to the blade when it is almost across the flight path to provide fore and aft pitching moments (I seem to remember 86deg phase lead being required in one piece of reading). Likewise, the roll axis is similarly out of phase on the rotorcraft.

So priority one is to stop the roll, otherwise you can induce dutch roll (pitch-roll coupling) or maybe even the equivalent of PIO (pilot induced oscillations).


PS There are some seriously weird aerodynamics on helicopters. There is even one part of the blade cycle where the air flows from the trailing edge to the leading edge of the blade! Seriously peculiar :facepalm:
 
Back
Top