Altitude Estimation with Pressure Sensors (STM32, Firmware + Hardware) - Phil's Lab #68

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we'll be using this little brain plus plus board with an stm32f4 microcontroller and a barometric pressure sensor to estimate changes in altitude thank you very much to altium for sponsoring this video the little brain plus plus we'll be using in this video was actually designed using autumn designer if you'd like to give autumn designer a try for yourself you can go to autumn.com forward slash yt forward slash phil's lab for more information i also have various altum design videos on my youtube channel and also one in particular which gives you an overview in 20 minutes of how to design this little brain plus plus board thank you also very much to glc pcb for sponsoring this video the little brain plus plus was manufactured and assembled by them and in exciting news they now offer standard pcba rather than this economic pcba which is single and double-sided placement which means you can place components both on the top and bottom of the pcb which is pretty cool with some bga stuff coming in the future if you're interested in getting one of these boards for yourself or looking at the design all of the altium assembly and gerber files are in the little brain plus plus repo and my github account github.com forward slash pms67 first of all let's talk about how we even get altitude from pressure measurements in essence it's the basis that atmospheric pressure changes depend on the height this is due to the weight of air above so the higher we move up essentially and start from the earth's surface and move up the less weight of air is above us so we increase our height and we decrease our pressure the opposite is true as well so if we start at a certain point above earth for example and the lower will move down the more weight of air will be above us so as we decrease in height the pressure will increase and typically you will see plots such as the one on the right here where we start on sea level on the left so typically denoted by a height or altitude of zero meters starting at about 100 kilopascals and this non-linear relationship as we increase in altitude how much the total pressure drops therefore if we find some sort of way that we can measure pressure we can infer height from that and it's always important to note that the height is always relative to a given level and typically you will see that to be asl which is above sea level but we'll use a different reference in this example then of course naturally the question is how do we even measure pressure now there are many different ways and there's different types of pressures you might want to measure in different areas not just atmospheric pressure but for us easiest and cheapest are what's known as barometric pressure sensors typically they contain quite a lot of circuitry and sensors so if it's a resistive sensor which will give some sort of analog output voltage or current depending on the pressure you can see that's usually with some sort of porthole and the pressure sensor will be underneath temperature sensor will usually also be included for compensation calibration and so on to get the analog output to be digital in most cases you'll need some sort of a d converter processor which might apply some sort of linearization filtering and also provide a digital interface so there's quite a lot of things in a simple barometric pressure sensor however luckily for us because we're more of a higher level design in this case we just see a package like this and this is a very typical and common bosch bmp 180 pressure sensor we're going to be using something very similar and the pin out might be something like this we just have to apply power so the vdd and ground pins we can choose our interface either i squared c or spi and we can get digital data streams out once we have those broad pressure measurements we need to think about how do we even calculate height usually two main methods one is the first tier it's this barometric formula well we need to know the temperature we need to know the pressure various other constants gravity molar constants and so on so quite involved there's also a far simpler method which is based on hydrostatics so we have a change in pressure is it change in height times the density times gravitational constant now also notice the minus sign is because once we increase pressure we actually decrease in height so in both of these formulas and both of these methods we have several problems first of all the temperature influences the density it influences this formula directly density changes depending on height gravity change dependent height and other different factors so it's not as straightforward as plugging in new constants into here the question is also you see p0 p naught or p ground or h ground how do you define these reference levels what are these relative to for simplicity and as you've probably assumed we'll just go with the hydrostatic method we just need to know the density and gravitational constant and for our sakes we're just going to keep it really simple around sea level the density of air is 1.225 kilograms per meters cubed and the gravitational constant on the surface of the earth is about 9.81 meters per second squared and we're assuming these are both constant all we need to do when we initialize our system is then measure an average pressure which means we're essentially finding out p ground so our reference level which we talked about just a second ago so we're collecting a number of samples adding them together and dividing by the total sample count and that gives us p ground at age ground so age ground which is the height above ground or our reference level is then simply whatever the level the sensor happens to be on an initialization in my case i'm just keeping my sensor on a desk so that'll be my reference level in essence this formula is really useful for looking in changes in pressure and changes in altitude for example an aircraft or drone might use this it has a runway and we want to see what height it is above that runway or valve ground in any case regardless of which method we go with we'll need to filter measurements so raw measurements will be typically very noisy even if they've been processed already by the barometric pressure sensor we need to maybe bandwidth to limit them low pass filter high pass filter and so on we'll typically go with just a simple low pass filter the question is do we filter our raw measurements of pressure or do we apply this formula first and then filter for example our final altitude or altitude difference it depends on how you initialize your filter essentially p can be very large we saw you know up to about 100 kilopascals so if the filter starts at zero and has a very slow time constant it might take ages to settle to the mean of where p is usually at whereas h which is our height difference actually so h minus h ground always starts off near zero in this equation in any case you know it doesn't really matter because it's a linear mapping but you have to make sure you know with filtering initializations and that the filter is fast enough if you don't initialize it now moving on how do we actually apply a filter and there's many different ways there's much better ways for example butterworth or higher order filters but for this simple example we're going to use a first order digital low-pass filter remember we'll be doing this in the digital domain on an stm32 microcontroller so we need to design a digital filter i wouldn't be going over much detail here i do have an irr filter theory implementation video that's video number 32 for your reference if you want to learn more about irr filters we'll be going with a very simple irr so a filter employing feedback and it can be first order we have n or lowercase n as our sample number x is our input y is our output and we have a single filter coefficient and we'll call that alpha that's anywhere between zero and one essentially our current output y of n is alpha our filter coefficient times the previous output so y of n minus 1 plus 1 minus alpha times x of n which is our input our current input so you can see if alpha 0 y of n is simply x of n so we have no filtering if alpha is 1 the output is simply the previous output so we get maximum filtering so no pass through from the input so we can vary alpha from zero which means no filtering to one to maximum filtering depending what our needs are and we'll play around with that a bit later i've done some bode plots in matlab of these filters and i've just chosen 0.1 0.5 and 0.9 is coefficients and you can probably guess heavy filtering is 0.9 which is the yellow trace keep in mind this is an absolute scale and frequency on the bottom so dropping from one very rapidly down and attenuating quite a lot and even lower frequencies if we turn up alpha to 0.9 somewhere in the middle of 0.5 you can see the red trace is that frequency response and 0.1 we get very light filtering which is this blue trace and here's the phase also as well which will introduce some delay of course so let's move on over to looking at the hardware and then the implementation for our stm32 device before we get started looking at the software let's briefly familiarize ourselves with the hardware because we'll need this to then write the drivers see which i squared c pins the barometric pressure sensor on the bottom here is connected to the mcu with and so on i have the designs the little brain plus plus open altium and if you go to my github page as mentioned earlier you can get all these files and produce one of these boards yourself the main microcontroller is an sm32f411 so a fairly powerful microcontroller and i've got various peripherals to play around with attached to it the only one we'll be using today is of course this barometric pressure sensor which is an spl06001 i believe it's somewhat of a clone of the bosch bmp180 works in a very similar way you can either use spi-i squid c for simplicity i used i squared c because this enables me to set this interrupt pin so i can always trigger reads every time the barometric pressure sensor has new data available so this is connected by i squared c2 and this simple interrupt pin to our microcontroller over here other than that we have an led which means we indicate okay that things are working a 60 megahertz crystal a usb connection which is useful for relaying data as well as this tag connect debug header which i'll be programming device with the tag connect header is pretty cool as you can see up here it's a solderless header you need a special adapter cable just show you in a second but it lets you quickly program boards without having to solder an actual physical connector on and this is the specific tag connect cable i'm using it's the tc2030 with no legs so i can just plug it in and you have a nice retaining clip to hold it although it might seem a bit pricey to begin with this is really useful because you never have to sold on a connector anymore for debugging and programming i'm using my usual you know cheap st link of version 2 with an adapter cable for the tag connect header i'll leave a link to the technique products in the description below before we move over to stm32 cube ide where i'll show you the software setup and the drives and so on let's briefly look at the digital pressure sensor data sheet we'll be using this to estimate altitude from pressure so as i said before this is the spl o6001 and this was available at glc so that's why i just took it it's fairly inexpensive what we need to see is our supply voltage range that's that that's compatible with our board and of course that is and a pressure range which is important for us because it'll also tell us okay up to what altitudes can we measure so up to plus 9000 meters and down to minus 500 meters below sea level so this is great for us this is exactly the range we need for this absolute pressure sensor we can also see various accuracies temperature stabilities and so on so depending on your application what precision you actually need in your altitude measurements this will be very important i won't be going into too much detail in this video of how to write a driver for the sm32 devices and i squared c but i do have a rather lengthy almost 40 minute introduction of how to write a driver from start to finish going through the data sheet and then actual testing so i'd highly recommend that if you're interested in writing drivers here we now are in stm32 cube ide and i've done a very very basic setup of this stm32f411 in my p9 planning i have enabled my external crystal enabled usb serial wire debug i squirt c the barometer interrupt pin as well as my led output pin the parameter interrupt if i click on it is simply an external interrupt pin and then of course you also have to set up your interrupt controller by going to system call nvic and make sure xti line one interrupt is enabled so once we set up this this barometric pressure sensor it'll then trigger or pull bar end high which we can then trigger with an interrupt and perform our read and i'll show you how to do that in just a second in gpio make sure to go onto your interrupt and make sure it's on rising edge trigger detection and of course that depends on what you want to be looking at you can also do falling edge in certain cases in middleware because i want to stream data via the usb port i've enabled usb device and i've included the virtual com port driver essentially like a virtual serial port in clock configuration my input frequency of my crystal is 16 megahertz i selected high speed external crystal the pll clock and i'm running at 72 megahertz no we don't need much processing power for this now we're ready to browse through the main code and i've pretty much written all of this already from the slides we saw earlier and implemented the ideas we saw i've included my sp06 driver which i wrote and i'll see in just a second and go over what the functions are in that driver i have some defines we can play with for example the initial pressure sample count as we said before when we boot up the device or we want to measure our reference altitude or reference pressure level i'm counting in this case 50 samples adding them together dividing by 50 to give me an average reading as we saw before i also have a very simple low pass filter for this barometer and this is essentially the alpha value so the filter constant now the barometer is running at its own sample time which you can change with the register settings but i'm also streaming via usb and this is not happening so synchronously my sample rate of the barometer is about eight hertz and i'm so and i'm sending of data about five hertz to the usb so not particularly fast you can go fast of course but there's no need for us for this very simple demonstration for my altitude calculations on my relative altitude calculations i of course need some constants that's the density of air in kilograms meter cubed and i'm just assuming a fixed constant and of course this depends on temperature altitude and and many other things gravity of the earth i'm just assuming the earth's surface on an average 9.81 of course gravitational constant of the earth and the density there will change and that will influence your height or altitude measurement as well precious sea level we don't really need but we can see that as some sort of baseline that's about 101.3 kilopascals then i'm defining my barometer struct and we'll see the driver after this a data ready flag to make sure i can start processing once this is set just for me there are some data count and data rate variables just to see that i'm getting my eight hertz out and here we have the main part which is our process data i have a variable which contains the initial average pressure which we sample you know over the count we want to process pressure so after we perform our low pass filtering it was stored in this variable the relative altitude so once we apply our formula to that estimate altitude in meters and this is of course relative to the initial level for usb logging i'm also storing the raw pressure and pascals which we can then use to compare to the low pass filter value to see how much our filter is affecting the signal let's just jump down to int main for a second after initialization i initialize the splo6 which is our barometric pressure sensor and in case that doesn't work i simply turn on an led and say okay i'm not going to run any further to start my triggers with the interrupt i need to perform a single read this will then start my interrupt loop so once my interrupt is triggered remember we are trying to read if this pin goes high so rising edge detect the hardware abstraction layer of stm32 cube ide nicely provides me this callback and i just check if it's the barometer interrupt pin that is fired i set my data ready flag to one back in my main while loop i then check that data ready flag and then i can read my data from the barometer which also then clears the interrupt i can clear my data ready flag and then i can call my process barometer data function i also have a very crude timer running which then triggers every time we pass our desired sample time for the usb data streaming in this i just simply use the virtual com port and i've shown this in previous stm32 videos on my channel how to do this in more detail i'm simply streaming my raw pressure my process pressure which is essentially my low pass filter data and my calculated relative altitude all to the virtual com port and then toggling the led so i can see every time i've transmitted some data lastly and maybe most excitingly this is the process barometer function i store my raw pressure data so not filtered then i perform my raw pressure measurement this is a very simple first order iir low-pass filter so a feedback-based low-pass filter my output is my constant times my previous output plus 1 minus that filter constant times the current and we saw that from the slides earlier this if statement here is essentially just during initialization i count up to whatever sample count i want add up the pressures and once i'm done i divide that by the sample pressure count and say okay i've got my initial baseline pressure data so every time this stm32 almost starts up it'll compute the average pressure and of course you will have to keep the device on one altitude level while this is happening oh this is fairly quick so once i have my initial altitude calculated average once i have my current filtered raw pressure measurement i can subtract them from each other divide by the density and divide by the gravity on earth of course i can't forget my minus sign because as you move the pressure sensor up the pressure decreases so it's an inverted relationship so to speak and then i store that in the relative altitude and that's in meters and there's all there is to this main code just briefly the spl06 driver very straightforward driver i have my initialization function and i have a read function and a struct to the store all of my data i'm checking the device id making sure okay can we even read from this ice with c device i'm reading calibration coefficients so i'm just following the data sheet it tells me i need to read out all these calibration coefficients to make sure i can calibrate depending on temperature pressure and so on i set it to eight hertz with eight times over sampling i do the same for the temperature configuration i want continuous pressure and temperature measurements this is what these register right is doing here and lastly i'm enabling the data ready interrupt so only generating interrupt when the pressure data is ready i don't really care about temperature data at this point because this is a very crude implementation and i want this to be active high in my read function i'm just reading six bytes of data so three for pressure and three for temperature converting the raw uncalibrated pressure and temperature over here and then applying the calibration as per the data sheet to get my temperature and degree c and pressure in pascal finally i'm clearing the interrupt status register without this this won't work because it won't re-trigger the interrupt so this is very important and that's all there is to this driver i've uploaded the code to my stm32 device via the tag connect probe and initially let me just check that the interrupt is indeed firing and i'm getting data through so i'm using my digilent waveforms analog discovery pro connected via usb and i'm in scope mode so let me just probe the pin and you can see i'm getting periodic firings of the interrupt and this should be you know about eight times per second so this seems pretty close to start with so that's a really good sign it looks like we're reading data out i can of course also put my stm32 device in debug mode and set the breakpoint obviously run for a bit to start the initial calibration and then i'll just set a break point in my process barometer function so i can double click and you can see it's paused and i've variables monitored on the right side here so the pressure in pascal is about a hundred thousand and if you remember pressure at sea level normally is about 100 and it's about 101 000 so this seems like a pretty reasonable value the temperature in degrees c i've had this build on for a little while so it's around 33 degrees it's pretty warm here it's the summer currently so yeah maybe something around that that seems about right that's a really good starting point if i hover over my initial pressure calculation we can see we have about a hundred thousand as our initial pressure so that's that seems about right we divided by the right amount of samples raw pressure contains one value first value which is a low pass filter contains a slightly different one so that makes sense as well because they're not going to be identical the relative altitude and this is in meters remember so this will be scaled down quite a bit i haven't moved the board so it's about 0.5 centimeters so you know 0.005 meters so this seems about right to start with so we're getting fairly sensible values out let's move over and try and plot this data and first we'll look at the difference between low pass filtered and raw before we move on to the altitude measurement i've now uploaded my code again and this time i'm just essentially sending over usb the raw and processed data so raw first and then processed which is uh which is quite simply speaking just the low pass filter data i usually use putty or h term just to make sure i'm getting data out my serial port is com 5 and i can click connect and you can see five times a second we get our raw and processed data okay so this looks good it's changing it seems about right so let's open the serial oscilloscope so i've uploaded the new code so we can measure or rather see the differences between the low pass filtered and not low pass filter raw pressure to do that until also make sure the scaling is okay i've subtracted or rather inversely subtracted the initial pressure from both measurements so they're about centered about zero and we can easily see what's going on with the scales involved i can open serial oscilloscope which i'll leave a link to in the description below in my serial port serial port five and the bottom we can see the sample rate is five hertz which is exactly what we wanted then we go to oscilloscope channels one two and three and then adjust the scale so here we have two traces showing we have green and red so green is the low pass filter data and red is the raw data so to speak the way i can see that is because during very high frequency movements so you see when it's jumping around here the red trace is always slightly higher that in turn mean that the green trace or the low pass filter is attenuating these high frequency movements however during fairly steady state for some of this decline here the green trace follows the red trace fairly well remember we aren't applying a lot of filtering so our filter concert is set to about a quarter what we can already notice i mean this is now in the units of pascals we can see there's quite a bit of movement i've not moved the pressure sensor one bit so far so there'll be random walk there'll be bias there'll be drifting over time so we can only see maybe pressure sensors on their own aren't the greatest thing to rely on it also depends on what kind of accuracy we want which we'll see later in the altitude or the relative altitude measurements because pascals initially don't tell us very much but this is just to examine the low pass filter i can zoom out i'll start moving my pressure sensor or rather the board up and you can see because i've inverted the pressures i'm climbing up which is what we expect and i move the board down i'm putting on my table again which should be around zero and you can see it doesn't quite reach zero so it keeps drifting moving around so we're staying within a certain band so i can move it below the table after initial jump it actually goes below zero so our initial function or pressure sensing seems to work in some way such as increase the value of alpha to see how much filtering move we can increase to to get rid of some of these fluctuations so i've changed my low pass filter alpha from 0.25 to 0.9 and let me just upload that code and now let's look at our traces again what we really notice by increasing the low pass filter the coefficient quite a lot the green trace is far smoother it's basically ignoring a lot of this high frequency content which is what we expect so this steady state of behavior might be a bit nicer but of course this now introduces lag into the signal some sort of sort of delay so if we want you know fast updates want to see quick changes in altitude this might not be the most optimal so let me just start playing around with it i'm lifting the device up as you can see there's a lag during movement and at steady state this seems okay but as soon as i move it away from steady state there's quite a bit of lag between the green and red trace so the filtered and raw data so at steady state of course this is really nice what we want but for fast movements you know this isn't optimal so this means we should probably turn down our filter coefficient a bit somewhere in the middle 0.5 is probably a good bet so this is now with a low pass filter setting of 0.5 you can see again we have much more high frequency noise but the green trace the low pass filter trace does follow the raw data much better so if i start moving it around i move it below my initial level you can see these are a much closer match and we've attenuated some of the high frequency noise so this seems like a fairly good compromise but remember this depends entirely on your situation sometimes a very slow rise time or very heavily filtered signal is preferable to something like this but with our low pass filter being tested and working let's go over to altitude estimation so now i've uploaded the new code and all i've changed is that i'm just transmitting one float variable which is the relative altitude so we can see okay what kind of drift do we get for altitude if i'm just letting this ball be on the table what if i move it around what kind of accuracy can we expect so back to the sphere oscilloscope opening my port and i'm just getting one value out so here we are just plotting the relative altitude so relative word to wherever the board started and let's just watch this for a while i'm not touching the board i'm just letting it sit here and we can see the walk or the random walk this sensor is performing or other measurements are erroneously moving about our relative altitude notice the scale on the left we have a scale of meters so 0.0 0.02 so this would be centimeters then so you can see this random walk it goes below and above this zero line and it hopefully is constrained between plus and minus 10 centimeters even though you can see there's a tendency for this measurement to drift upwards and you can see it's starting to drift down a bit as well so for the way we are calculating the altitude you know with our constant coefficients we're not doing temperature or density of the air compensation we're getting about you know plus minus 10 centimeters so let's see what happens if i lift it above the table let's see if i can try and lift it about 10 centimeters above and change my scale and you can see it's moved up to about 20 centimeters i can move the ball down again and it takes some time for it to settle but it's moved back down to about you know 10 centimeters so this change is about 10 centimeters which is how much i moved i can also move it down so below the table you can see we have these initial transients so we're not getting i mean i'm just doing it by eye trying to move it down 10 centimeters but we definitely see a movement but they you might get an error of plus minus 5 or 10 centimeters again just lying laying the the pressure sensor on the table you can see it keeps trying to climb to mean of about 10 centimeters even though initial starting point as we saw on the left you know was around zero so it's definitely drifting away from its center and we are fluctuating quite a bit we could of course apply more low-pass filtering and we can also set thresholds so it's between zero and five we just clamped that to five which between five and ten would just clamp that to ten and so on so you can probably hard gate this pressure signal this altitude signal to get something more reasonable out of this also keep in mind this is a very inexpensive very small pressure sensor so you can get pressure sensitive of higher quality and more precision and also you can of course improve the code and filtering as well i do hope this video gave you a small insight into how to interface with the pressure sensor and how to estimate changes in relative altitude look forward to seeing you in the next video and thanks again for watching
Info
Channel: Phil’s Lab
Views: 17,125
Rating: undefined out of 5
Keywords:
Id: Itw6rxeYACY
Channel Id: undefined
Length: 26min 4sec (1564 seconds)
Published: Wed Jul 27 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.