DIY electronics

The Rocketry Forum

Help Support The Rocketry Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
8-bit MCUs like PICs and Atmels work great with applications like most of ours, because the sensors generally deal with bytes anyway. If you had a 32-bit MCU you'd still have to do all of the bit shifting etc. to get the byte-level data into longs and you'd still have to wait for the sensors and the serial memory (3-5 ms per write for EEPROMS!), so I don't see a significant reason to go looking for a "faster" processor. There are tons of FREE tools available for 8-bit MCUs so from a DIY point of view it's a natural choice.

eeproms need to, like 8bit processors, be left in history where they belong :) Sure, they have their place... but unless you're just storing a couple of config variables there is no reason not to store a full page of flash in RAM then write it to a flash chip. A flash chip has thousands of times the size of an eeprom and is thousands, if not millions of times faster to write to.

Needing to do bitshifting really depends on the peripheral you're dealing with. If it's SPI or I2C, most modern architectures will take a 32bit variable and shift it out just fine with no clock cycle overhead.

You can get an ARM chip that is smaller, faster and has more memory/flash than an 8bit micro, for less price. Why 8 bit is still used by hobbyists is beyond me. NXP, TI, ST and Freescale all have free IDEs - several of them using CodeRed (Eclipse) with a 128k or something compile size limit. Not only do you get a real IDE (not a glorified copy of Notepad like the Arduino "IDE") - you also get realtime, on chip, in circuit debugging and state inspection. You can view the stack, inspect registers, step through code and even roll back the stack - I've love to see that done on an 8 or 16bit chip for less than $500.

ARM cortex has bought high power embedded processing well within reach of the hobbyist masses. NPX/EmbeddedArtists LPCXpresso boards are pretty much all under $35, include a SWD JTAG onboard (which can be chopped off and used separately) and have a full featured IDE. These support most of NXP's ARM Cortex family giving you something for every application. CodeRed is free for use with these, and there is an active community and heaps of examples. ST's STM32 discovery boards are cheap to - the STM32F4Discovery is $14.90 on digikey, has a SWD JTAG onboard, 1mb of flash 192k of ram and runs at 168mhz. It also includes a full IDE. IDE + JTAG + dev board (with accelerometer, microphone, audio DAC onboard) for under $15 - crazy!

An LPCXpresso will fit in most rockets, and they have breakout boards smaller than the arduino minis - with USB on chip.
 
Why 8 bit is still used by hobbyists is beyond me. NXP, TI, ST and Freescale all have free IDEs - several of them using CodeRed (Eclipse) with a 128k or something compile size limit.

Its very simple. Hobbyissts are not firmware professionals. 8-bit is much easier to learn from zero. Compare any 'LED Blinky' sample code between AVR and ARM to see the difference. I know 'professional' ARM programmers who still don't understand startup code. Also 8bit micros have PLENTY of power for the relatively modest technology needs of rocket altimeters.

I use both 8-bit (ATMEL) and ARM (IAR) environments for a variety of applications. ARM is most definitely the future but 8-bit microcontrollers have their place.

As for IDEs, ATMEL Studio 6 is as nice an environment as Eclipse or even IAR. (But I like the LPCxpresso system ALOT).
 
Nice project. Some tools/tips, in case they are helpful:
1. Try a $40 toaster oven for soldering (more uniform heating)
2. Get a thermo probe lead for your multimeter to judge the end of the soldering cycle (basically, take to over 205C (400F), then let cool.
3. Cheap Mylar stencils will let you easily place solder for fine pitch components (many/most new cool chips are leadless and fine pitch)
4. Use integer math as a replacement for floating point. As a simple example, instead of x * 21.63, do (x * 2163)/10
5. It's fine to use 8-bit processors when that's all the job needs. Some of them are incredibly power-efficient. Power efficiency is the most important factor in modern battery-powered mobile designs. (Once your battery dies, it stops working.)
6. Power regulators are cheap (< $0.20). Set up your board to use one level (3.3V is convenient), and run everything from that (you'll just have to avoid 1.8V/2.5V parts).
7. It's kinda hard to jump from one processor family to another, because the learning curves can be hard. People who have learned the dark secrets of one processor family aren't very anxious to dive into others. For instance, Jolly Logic's products use Microchip controllers. There were really tight reasons to do this for the first two products (embedded LCD drivers, unique in cheap controllers to Microchip), but even upcoming products use Microchip controllers (albeit 32 bit), though at that level there's lots of competition that might be just as good. But we're used the peculiarities of Microchip, so...
8. Up until now we've used the Bosch part for pressure. It's rather expensive and requires a lot of post-processing, but it has super performance. We're looking at the new ST part, the LPS331. It's smaller, and appears pretty easy to use. We're trying to interpret the specs now to figure out if overall it's a good choice.
 
I am very impressed. I think it is all above my capabilites.

Where did you learn to do this?
 
Very impressive. Thanks for sharing the project. If you need summer tets conditions, come south to SC for some better weather.
 
My chip spits out the reading as a 24 bit integer using three registers. That number needs to be divided by 4096 to get the pressure in millibars, so AFIK that result needs to be floating point, unless I misunderstand something? For that reason I currently have the long int output data being divided by 4096.0 in order to get the float.

Code:
byte H = readRegister(0x2A);
byte L = readRegister(0x29);
byte XL = readRegister(0x28); 

pressure = long(H) << 16 | long(L) << 8 | XL;

return (pressure / 4096.0);

Ooh ooh, pick me....!

Dividing by 4096 is the same as shift right 12 times

Code:
return (pressure >> 12)
 
That doesn't make any sense. You're getting an integer quotient and throwing away the remainder so now your resolution is over 27ft. Google it.


Ok, shift once, multiply by 10, then shift 11. Resolution is now 2.7 ft. All integer math.
Or shift twice, multipy by xx ...., just watch for overflow before you scale.

You can maintain any precision you want and still stay with integers. Just scale and keep track of where the decimal point would be.
 
Is the pressure an end result for your purposes or are you using it only as an intermediate result (to calculate altitude etc.)? If the latter is the case you can continue your calculations with 1/4096th mBar or any other arbitrary unit that happens to be suitable for you.

Reinhard
 
sensor output / 4096 = pressure mbars
altitude = [mbars(ground) - mbars(altitude)] / .036622931

If your concerned about getting less than 30ft accuracy, the above equation would not be the best model for. Pressure versus altitude is not linear. A quadratic fit would be better or piece-wise linear model would be much better. The error due to a linear approximation will be much larger than the temperature effect you are concerned about.

To get altitude you want to calculate: Altitude(above ground) = Altitude - Altitude(ground). The Pressure and Pressure(ground) will have different divisors to determine their altitudes.
 
Last edited:
There are a number of factors which affect accuracy. Just to further the discussion for those who are into this sort of thing:
1. Discrepancy between ambient pressure outside the rocket and in the sensor
2. Sensing accuracy
3. Accuracy in calculations using the Standard Atmospheric Model
4. Inherent inaccuracy of the SAM at standard conditions
5. Deviation from standard conditions

Proper venting handles #1. A good sensor properly used handles #2. Some of the math tricks that have been discussed address #3. The SAM is very good and handles #4. Handling #5 requires an external (not in-chip) temperature sensor and an additional input of actual ground elevation or other data somehow to calibrate for weather deviation from the Standard Conditions assumed by the SAM. Not usually done.

The Jolly Logic AltimeterOne and AltimeterTwo use purely integer math, including a piece-wise linear interpolation of the SAM, where the "s-shaped" SAM curve is broken into over a dozen straight lines so that at no point are the lines > 1 foot away from the SAM. Once you have the pressure, you look up the proper m and b from a table so that y = mx + b, where x is pressure and y is altitude. All of the numbers deliberately are kept large and small enough so that the rounding error is << 1 foot.

Probably more info than anyone cares about, but in case you're interested, thought I'd share....
 
....use purely integer math, including a piece-wise linear interpolation of the SAM, where the "s-shaped" SAM curve is broken into over a dozen straight lines so that at no point are the lines > 1 foot away from the SAM. Once you have the pressure, you look up the proper m and b from a table so that y = mx + b, where x is pressure and y is altitude. All of the numbers deliberately are kept large and small enough so that the rounding error is << 1 foot.

QUOTE]

Also if you are using a digital baro sensor with limited altitude range (<30K ft MSL) you can also opt for a lookup table (memory is cheap) and use no math at all....:D
 
After some playing around, it turns out the factor I have of 0.036622931 mbar/ft multiplied with the 4096 reduction factor of the chip output gives a value of 150.007525376. So dividing the chip's output by 150 gives some very accurate results, more accurate I'm sure than the floating point math.

This is pretty much what I meant with arbitrary units. Your calculation works quite fine without the pressure ever being expressed in mBar, torr or another "official" unit.

Code:
Altitude = (reading at ground level - reading at altitude)/150

Integer division will always round down, so you would get results like 299/150 = 1. You can improve that without a big performance penalty:
Code:
Altitude = (reading at ground level - reading at altitude + 75)/150


Reinhard
 
The only problem is that pressure change is not linear with altitude, which is why the FP comes into play in the first place. Specifically, it's Altitude{ft} = 44330 * (1 - Pressure{hPa*100}/101325)^1/5.255). Now, the exponent is relatively linear for small changes in pressure, so you can make a graduated lookup table and use that to simply multiply by the pre-calculated exponential factor for a given range of pressure readings. This works fine, assuming that you have enough flash memory to burn the table. With an ATTINY, you may have issues.

If you already have the pressure reading and the ONLY floating point math that you are going to be doing is the altitude calculation, I say go for it. Trying to go around it by using integers and lookup tables is adding a lot of extra work, and I'm no so sure that the extra code and cycles are going to end up saving you anything in the end.


After some playing around, it turns out the factor I have of 0.036622931 mbar/ft multiplied with the 4096 reduction factor of the chip output gives a value of 150.007525376. So dividing the chip's output by 150 gives some very accurate results, more accurate I'm sure than the floating point math. In other words what I'll do is:

Code:
Altitude = (reading at ground level - reading at altitude)/150

I've verified this by calculating the reading I would expect at sea level vs 2000ft:

Code:
1013.25 mbar * 4096 = 4150272 (expected output from the chip at sea level, known pressure 1013.25mbar)

2000ft * 0.036622931 mbar/ft = 73.245862 mbar difference
1013.25 mbar - 73.245862 mbar difference = 940.004138 mbar
940.004138 mbar * 4096 = 3850256.949248 or 3850256 (expected output from the chip at 2000ft ASL)

So if my altimeter reads 4150272 at ground level and 3850256 at 2000ft,

Code:
(4150272 - 3850256) / 150 = 2000.106 ft.

That looks good enough to me.

Furthermore, that number I have is the conversion of mbar/ft at 15C, the number is 0.038640888 at 0C, which makes my overall divisor 158 instead of 150. These are values I found on the interwebz, to get more accurate at different temperatures I'll have to dig out my old Thermo book, but a linear approximation between the two values would probably suffice.
 
Last edited:
You really need to have the electronics in a payload bay with properly sized ports, that may be your issue. There's a LOT of airflow going on around there so ambient pressure detection is undoubtedly suspect.

You should be able to add a 4"-6" payload section to your Vagabond without affecting its stability, you probably want a bigger engine though, something like an Aerotech RMS 24/40 E28 so that it doesn't weathercock. If you don't do RMS yet, the E20 SU should suffice.


I gave the altimeter its first test today, strapped to my Vagabond. It registered 182ft on a D12-5, so something didn't go right. I haven't implemented any SAM adjustment yet but I think the altitude should have been about twice that. I'm guessing that's too much error even with adjustment.

I think the next step is to set up a logging mechanism so I can see what's going on.

View attachment 103768

The good news is that it detected launch and I could hear it beeping out the altitude from about 50yds away.
 
Oh, then get a pack of F24 loads. You'll never use BP motors again once you hear them light up. :)

The Vagabond is a really good platform for this kind of experimentation, I went through three of them testing the Eggtimer. It's a lot cheaper than doing it with 29mm or HPR and if you trash one it's only $20. The StormCaster looks promising too, it's got thru-tube fins but you'll want to replace the balsa fins with basswood or plywood.

Agreed, I'll have to make a BT-60 add-on bay. I have a 24/40 case and a couple E18 reloads. Maybe before then I can implement some logging too so I can see what it's doing.
 
Wow, I'm jealous... you can actually launch at your local schoolyard? Here in CA you have to go through hoops to get permission to launch, so pretty much only club-supervised scheduled launches are allowed. Fortunately I live 3 miles from the only place in SoCal where you can launch without driving out to the desert, but it's still a pain dealing with all of the club politics. There used to be an open launch site in Orange County, but they closed it and made a golf course out of it... go figure.

Yea, I had a 3 pack that all went into my Ventris. Unfortunately I rarely get a field big enough for these so I mostly have to stick with BP's. People might start to complain if I light up the composites at the school yard. :)
 
Maybe you can find some flying buddies and start your own NAR chapter...

I've driven up to Tripoli Central California because I wanted to launch something higher than the local ceiling, 4 hour drive. It was worth the effort, I was testing some electronics/software and I got six DD flights in that day.

People in CA are crazy about their dogs, they really do have those chihuahuas in purses like you see on "Legally Blonde". My kids play travel hockey, one of the team moms brought it to the rink with her all the time. Poor thing shivered like crazy...

That's a bummer. The flip side of the coin is here where there's no club within a 2.5 hr drive, so I launch alone with my wife spectating. As for regulations it's pretty much wild west style around here now. The other popular pastime at the schoolyard is walking your dog without a leash- I bet that wouldn't fly where you're at either.

The funny thing is we're surrounded by miles and miles of farmland outside the city. You'd think that would be great, but in the summer the fields are off limits with crops planted, and the spring and fall tend to be wet- so the stars have to align for there to be nice weather and the fields aren't giant mud pits!
 
Looks typical to me...

This data would probably respond well to an averaging filter, average the last 10 samples and add 90% of that value to 10% of the current sample to get your filtered value; then take that and make it your new average for the recursion. There will be a slight lag between the real-time data and the filtered result, but it will work just fine for an altimeter. This filter is ideal for an ATTiny because it uses very little flash or memory.

I dusted off this project the other day. I decided to back up and take care of the noise issue, so I removed my sensor from the board I built and put it on an Arduino proto-shield that the local Radio Shack had on the clearance rack ;) Now it's much easier to make changes and test.

Adding capacitors for power filtering didn't seem to make any difference, but the data sampling method sure did. I WAS using the "one shot" method for this chip, basically requesting a new reading and then retrieving that reading. It performed much better when setting it to sample at a specified rate (25hz) and simply reading those values as they were generated.

View attachment 135951

This is just the raw data while sitting on my desk, no filtering, but its looking better already!

Can anyone who's experienced with these kind of sensors determine if these results look reasonable before filtering? This is also using the internal 512x oversampling.
 
Any ideas on why I'm getting these wacky readings? Is my sensor just too sensitive?

I would need to see the raw data before being able to even guess. A schematic would be nice too.

From the previous discussion of floating point and such it appears that you are mangling the data on board. There is zero need to do that. At best you need to do one conversion for an apogee value.

Oh, that Kalman filter implementation you used is very poor. It starts out with wildly wrong gains because the covariance matrix is initialized to nothing like the steady state value. The gain should converge to a constant value so all that mucking about with covariance is a waste of time. Fortunately not a big waste with a single state but still a waste

The KalmanCalc() function could be replaced with a single line:

return (kalman_x += (kalman_k * (altitude - kalman_x)));

A Kalman filter with only one state and such a simple model (constant altitude) doesn't really play to the advantages of the Kalman filter.
 
Here are my raw readings. They are the 24 bit reading that becomes absolute hPa when divided by 4096. The first reading is the "Base" which is an average of 100 samples after power up. The graph above is (base - momentary)/150 and is for now just an estimation to make it look like the flight curve.

I suspect a problem with the serial interface to the pressure sensor. The code would help.
 
Dave:

I assume he got the code from Boris, who got it from me. It's derived from some code by Pengu Robotics, see:

https://pengu.student.utwente.nl/wordpress/?p=116

I'm nowhere near the math wiz that you are, but I recognize that you are correct in stating that it's not a "true" Kalman filter because there it's single-state (altitude). This makes the covariance matrix reduce to a single value, which Pengu kinda sorta states in their article. Your reduction of the formula basically makes the kalman_k value a weighted-average factor (approx .2). I tried a number of weighted-average schemes, including different factors for older vs newer samples, and the Pengu filter does seem to give the best smoothing. Going back and looking at some spreadsheets that I did when I was working out the factors, it does seem that the kalman_k factor converges to the constant .2, so that's probably a worthwhile piece of code-saving, assuming that the filter still works the same (as it should.)

Do you know of a better single-state filter? I'm sure pick1e, Boris, and Leo would all appreciate it.


I would need to see the raw data before being able to even guess. A schematic would be nice too.

From the previous discussion of floating point and such it appears that you are mangling the data on board. There is zero need to do that. At best you need to do one conversion for an apogee value.

Oh, that Kalman filter implementation you used is very poor. It starts out with wildly wrong gains because the covariance matrix is initialized to nothing like the steady state value. The gain should converge to a constant value so all that mucking about with covariance is a waste of time. Fortunately not a big waste with a single state but still a waste

The KalmanCalc() function could be replaced with a single line:

return (kalman_x += (kalman_k * (altitude - kalman_x)));

A Kalman filter with only one state and such a simple model (constant altitude) doesn't really play to the advantages of the Kalman filter.
 
Also, I know I'm not getting parts of different readings mixed together because I have set the bit for "block access control" to prevent the sensor from storing a new reading until all bytes of the previous reading have been accessed.

Except that the order you access the data matters. It should be XL, L, H because once you access both the low and high bytes the registers are unlocked. If you use the multi-byte read starting at XL this takes care of itself.

But these code fragments are not very helpful. How is the sensor initialized? How are you requesting a conversion? How often? The details matter a lot.
 
Do you know of a better single-state filter? I'm sure pick1e, Boris, and Leo would all appreciate it.

A single state Kalman filter uses a model of constant altitude which obviously doesn't match reality. I cannot think of any filter that would do better (that doesn't mean that one doesn't exist, just that I can't think of it at the moment) without adding states to estimate velocity and acceleration.

I am assuming that you have read my R&D reports but if not, follow the link below...
 
Thanks. Maybe what we're looking for is something that simply smooths out the peaks and valleys in the velocity curve better. I read your R&D report awhile ago, it's excellent, but with only a pressure sensor it's not really applicable because there's nothing relatively "easy" (i.e. a decent acceleration reading) to feed into the filter as a second source of data.

I guess one could use a dV/dt and a dS/dt from the last two previous altitude samples to estimate the next altitude value, and plug that into some filter. As you know, deriving velocity from pressure altitude data is somewhat error prone, and deriving acceleration from pressure altitude data is damn near useless because the errors are squared. Maybe once you plug those values into the real-time data with some kind of delta correction it works better...

A single state Kalman filter uses a model of constant altitude which obviously doesn't match reality. I cannot think of any filter that would do better (that doesn't mean that one doesn't exist, just that I can't think of it at the moment) without adding states to estimate velocity and acceleration.

I am assuming that you have read my R&D reports but if not, follow the link below...
 
They later refer to XL as "LSB" and H a "MSB" so if what you're saying is the case, their documentation isn't very clear.

I looked at it again and that is the way it reads now. I have no idea why I thought otherwise.

One detail that the data sheet doesn't address has to do with the timing of reading the registers. It says that reading the MSB or LSB will lock out updates until the LSB/MSB is read. What it doesn't say is what happens if you start your read in the middle of an update. Is the update to all three registers synchronous or is there a delay between writing to the individual bytes?

As I mentioned a few posts back I was originally calling for a sample using "one shot" but found the results were much better just setting it to 25Hz.

I can see that now in the configuration. But what I don't see is any check to see if data is ready. The way I normally code this sort of thing is with interrupts. The pressure sensor does have an interrupt output pin that you could use.

Note that 25Hz is going to be very approximate since the device is using an internal RC based clock.

If you can't use an interrupt pin then use the status register to control the loop. If you need good timing data you will need to add that. Assuming you have a crystal based clock available.
 
Thanks. Maybe what we're looking for is something that simply smooths out the peaks and valleys in the velocity curve better. I read your R&D report awhile ago, it's excellent, but with only a pressure sensor it's not really applicable because there's nothing relatively "easy" (i.e. a decent acceleration reading) to feed into the filter as a second source of data.

I guess you missed the part where I talked about a pressure only filter. With code.
 
Back
Top