# Thread: Airspeed from MPX5500DP differential pressure sensor using a PIC16F88

1. ## Airspeed from MPX5500DP differential pressure sensor using a PIC16F88

Hey All,
I am working on a project to calculate the airspeed from a pitot tube that is connected to a differential pressure sensor (MPX5500DP) and then output it to an LCD screen (44780 Driver) using a PIC16F88. I have very little background in picbasic and I am having a hard time writing the code.

To calculate the velocity from the pressure, I want to use the equation

Airspeed = sqrt(2P/1.2) where 1.2 is the density of air

But, the problem is I need P from my sensor. How would I go about getting this value?

The basic setup is I have the Vout from the sensor going through a non-inverting amplifier (LM741C). So the amplified voltage values range from something like 9V to 13V, depending on what the pressure is on the sensor. I know that I need to turn on the A/D conversion and right justify to get 10-bit results, but I am stuck after that. How do I write the code to take the voltage coming in to the pic and turn that into a value for pressure. I've read several other threads involving pressure sensors but none of them were differential pressure sensors.

My current code is very short, but its all I could manage to get together from my research.

'Identify and set the internal oscillator clock speed (required for PIC16F88)
Define OSC8
OSCCON.4=1
OSCCON.5=1
OSCCON.6=1

'Set Up A/D Conversion
TRISA = %11000000 'sets RA6 and RA7 as inputs and the rest as outputs
ADCON1.7 = 1 'Right justify for 10-bit results
Pause 500 'Wait .5 seconds for warm up

I've attached a wiring diagram of how I would like to wire this set up.

Any help would be greatly appreciated. Let me know if I need to provide more information. Again, I am not very familiar with picbasic so the more simple it is, the better.

Thanks!

-Marcus

2. Welcome to the forum.
Here is a similar one. See if it helps.

3. Dave,

Thanks for your help. That makes a huge difference. Few questions for you though. Since this sensor will never hit it's maximum pressure reading at any point, is there a way to cut the max pressure to a tenth of what it is? i.e. the MPX5500DP has a Pmax of 500 kpa, if I cut that down to 50 kpa (500 / 10), would that make any major difference in my calculations?

So, from the copying from the other thread and plugging in my numbers.

"Using the old formula of
y = mx-b
y = output 'Volts
m = slope
x = input units
b = offset
wanting to read form 0 to 500kpa.
Output is 10 to 14 volts.

Start off by looking at the output in volts. I have a 4 volt span. Giving a span of 500 / 4 = 125
m = 125

The offset. Starting at 10 volts. 10 volts = 0 kpa. The offset is 10 * 125 = 1250
1250

Plug all this into the formula and lets say the input is 14 volts.(full scale)
y = (125 * 14) - 1250
y = 500

Now convert this to an 10 bit PIC resolution.

10 bits ADC = 0 to 1023, 1024 steps.
At 14 volts one volt of input will will read 73.
Spanning 4 volts or 292 steps (4 * 73).

New value for m. 500 / 292 = 1.7123
m = 1.7123

The new offset starting at 730, (10 * 73).
730 * 1.7123 = 1250
b = 1250

y = (ADC * 1.7123) - 1250
y = 500kpa

Correct?

But, then in the code you multiple m by 10,000 and b by 100, what does this do for the values? Is that simple to prevent truncation in the program?

"Code:

' m = 0.00479
' b = 0.98
' y = (ADC * 0.00479) - 0.98
' y = 3.92kpa
M CON 479 'm = 0.00479 * 10,000
B CON 98 'b = 0.98 * 100
ADC VAR WORD 'INPUT FROM SENSOR
Y VAR WORD 'KPA
Z VAR WORD 'DUMMY VAR
Z1 VAR WORD 'DUMMY VAR
'V = SQRT((2 * (Y/1000)) / 1.225)
V VAR WORD 'METERS/SECOND
D CON 122 'AIR DENSITY

START:
ADC = 1023 'FULL SCALE HARD CODED, NO SENSOR
Z1 = DIV32 1000
Y = Z1 - B
Z = (2 * Y * 10000)
Z1 = DIV32 1000
V = SQR(Z1 / D *100)
LCDOUT \$FE,1,"KPA= ",DEC Y/100,".",DEC Y//100
LCDOUT \$FE,\$C0,"M/S= ",DEC V
PAUSE 250
GOTO START"

I really appreciate the help.

-Marcus

4. Output is 10 to 14 volts.
Remember that the MCU can not handle 14 volts. 5 is the max. You can use a voltage divider to bring the voltage down though. Do a 3 to 1.

To tighten the readings up you can add a VREF value to the MCU via voltage dividers.

But, then in the code you multiple m by 10,000 and b by 100, what does this do for the values? Is that simple to prevent truncation in the program?
Yes, the decimal constants are converted to whole numbers for calculating.

I will suggest setting up a test board with some pots and play with the ADC some to get a feel for it.

5. Oh jeeze. I should have realized that... okay. Well I can fix that by bumping down the gain on the op amp by swapping resistors so that's not a problem. I'll work on this and see if I can't get something working. Thanks for your help! I'll probably be back with more questions later.

6. Originally Posted by marcusvm
I'll probably be back with more questions later.
We will be here. Good luck!

7. If you have an op-amp in a non-inverting configuration, you have two resistors: one (call it R1) from the op-amp output to the inverting input, and another resistor (call it R2) from the inverting input to GND (usually). The gain will be 1+ (R1/R2). If you tie the end of R2 that normally would go to GND to a voltage instead, the output will be shifted. The gain from that point will be (R1/R2).

For example: If you have an input that goes from 5 to 6 volts, and you need to change it to one that goes from 0 to 5 volts, you need a gain of 5 (1 volt change going in, to 5 volts change at the output). You could choose R1= 4K and R2= 1K. The gain would be 1+ (4K/1K) = 5.
Now you need to shift it "down" to the 0 - 5 V range. The gain to the inverting input will be 4 (4K/1K), so you need to apply 5V/4 = 1.25V ABOVE 5V = 6.25V to the end of R2.

Remember that if you use a voltage divider to provide this 6.25V, the thevenin resistance of the divider will be added to R2's value. The best way around this is to connect R2 to the output of a unity-gain op-amp, and drive THAT op amp with a divider from a voltage reference. And one final thing - if you don't have a negative voltage source for the (-) power pin of the op-amp, you will need a rail-to-rail output type in order for the output to get to near zero volts.

8. Thanks for the Help.

So, I got the op amp all set up to keep the voltage under five volts. I can't believe I let that slip my mind when I was setting this up.

Now, for coding, to get the analog output of the sensor to a use-able number in the pic. I understand that the pic has to have the AD conversion turned on.

So, I want to hook up the analog voltage input on to pin RA7 on a 16f88. Would this be the correct code to do that

TRISA = %10000000 'sets RA7 as input and the rest as outputs
ADCON1.7 = 1 'Right justify for 10-bit results
Pause 500 'Wait .5 seconds for warm up
But then, I'm stumped on getting the digital value from that pin to a value to plug into the equations for velocity.

I'm sorry I'm so slow at this. I'll end up in the lab at 6AM tomorrow working on this so I want to make so I have as much information as possible to get as much done as I can.

-Marcus

9. You can take a look at this and the data sheet to help you figure it out.
Basics for reading an ADC with a 0 to 5 volt input and the chip running on 5 volts.
Change as needed.
Code:
```<font color="#000000">    <font color="#008000"><b><i>'16F88 10 BIT ADC TEST  FOR CHANNEL 0
</i></b></font><font color="#FF0000"><b>DEFINE </b></font><font color="#0000FF"><b>OSC </b></font><font color="#800000"><b>4
</b></font><font color="#0000FF"><b>OSCCON </b></font>= <font color="#800000"><b>%01100000
</b></font>@ <font color="#0000FF"><b>__config _CONFIG1</b></font>, <font color="#0000FF"><b>_INTRC_IO </b></font>&amp; <font color="#0000FF"><b>_WDT_OFF </b></font>&amp; <font color="#0000FF"><b>_LVP_OFF </b></font>&amp; <font color="#0000FF"><b>_MCLR_OFF </b></font>&amp;<font color="#0000FF"><b>_CP_OFF
ANSEL </b></font>= <font color="#800000"><b>%00000001
</b></font><font color="#0000FF"><b>TRISA </b></font>= <font color="#800000"><b>%11111111

</i></b></font><font color="#0000FF"><b>START</b></font>:
<font color="#FF0000"><b>HIGH </b></font><font color="#0000FF"><b>PORTB</b></font>.<font color="#800000"><b>3    </b></font><font color="#008000"><b><i>'HEART BEAT LED
</i></b></font><font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>250
</b></font><font color="#FF0000"><b>LOW </b></font><font color="#0000FF"><b>PORTB</b></font>.<font color="#800000"><b>3
</b></font><font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>250
<font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>50
</b></font><font color="#008000"><b><i>'BELOW SHOWS THE 10 BIT READING OF ADC0 IN VAR CHAN0
</i></b></font><font color="#FF0000"><b>SEROUT2 </b></font><font color="#0000FF"><b>PORTB</b></font>.<font color="#800000"><b>2</b></font>, <font color="#800000"><b>16780</b></font>, [<b><i>&quot;CHAN0 &quot;</i></b>,<font color="#FF0000"><b>DEC </b></font><font color="#0000FF"><b>CHAN0</b></font>,<font color="#800000"><b>\$a</b></font>,<font color="#800000"><b>\$d</b></font>]
<font color="#FF0000"><b>PAUSE </b></font><font color="#800000"><b>250
</i></b></font><font color="#FF0000"><b>GOTO </b></font><font color="#0000FF"><b>START

</i></b></font><font color="#0000FF"><b>ADCON1 </b></font>= <font color="#800000"><b>%10000000      </b></font><font color="#008000"><b><i>'SET FOR 10 BIT
CHAN0</b></font>.<font color="#0000FF"><b>HighByte </b></font>= <font color="#0000FF"><b>ADRESH  </b></font><font color="#008000"><b><i>'PLACES THE HIGH AND LOW BYTE
</i></b></font><font color="#0000FF"><b>CHAN0</b></font>.<font color="#0000FF"><b>LowByte  </b></font>= <font color="#0000FF"><b>ADRESL   </b></font><font color="#008000"><b><i>'INTO VAR CHAN0
</i></b></font><font color="#FF0000"><b>RETURN

</i></b></font><font color="#FF0000"><b>PAUSE   </b></font><font color="#800000"><b>50
</b></font><font color="#0000FF"><b>ADCON0</b></font>.<font color="#800000"><b>2 </b></font>= <font color="#800000"><b>1
</b></font><font color="#FF0000"><b>WHILE </b></font><font color="#0000FF"><b>ADCON0</b></font>.<font color="#800000"><b>2 </b></font>= <font color="#800000"><b>1</b></font>:<font color="#FF0000"><b>WEND
RETURN

</b></font>```

10. Charles,
Would you consider writing an article for the wiki covering different ways of using op amps?

11. I guess I could in the next week or two.

12. Thanks for the help you guys. I'll look through the code and try to decipher what exactly its doing and make sure I have it set up for my application.

Is the serout2 command just sending the data to the lcd? Rather than using an LCDOUT command?

Got to the lab early this morning, got my LCD up and running. Went to reconfigure my op amp and find out its grounding something across the +-15V pins. No idea what is going on because last time I used the circuit it was working perfectly. Oh well, good thing I've got another 4 op amps on the way!

13. I waa displaying the data on a terminal with SEROUT2.

14. So, after working it over a little, this is what I've got.

'Using PIC16F88
'Identify and set the internal oscillator clock speed (required for the PIC16F88)

'Using configuration bits of the following
'Oscillator: INTRC-OSC2 as RA6
'Watchdog Timer: ON
'Power Up Timer: ON
'Code Protect: Off
'RA5/MCLR pin function select: RA5 (to use this pin as extra I/O instead of MCLR)

DEFINE OSC8
OSCCON.4=1
OSCCON.5=1
OSCCON.6=1

'Turn on and configure AN4 (A/D convertor on pin 3)

ANSEL.4=1 : TRISA.4=1 'sets up the A/D conerter on RA4/AN4 (pin3) and sets it to an input
ADCON1.4=1 'have 10 bits be right justified
DEFINE ADC_CLOCK 3 'Sets clock to internal oscillator
DEFINE ADC_SAMPLEUS 10 'Pause for sampling, I don't actual use this anywhere in the program

'Initialize I/O pins
TRISB=0 'Set PORT B pins to all outputs
TRISA=%00010000 'Set PORT A pins to output except for RA4/AN4(pin 3), it will be set as an input

'Declare variables

ad_word Var Word 'Word from the A/D converter (10 bits padded with 6 0's)
P Var Word 'P is the calculated pressure variable from the reading of the pressure sensor
V Var Word 'V is the calculated airspeed from the pressure value
X Var Word 'X is a variable taking place of the calculation 2*9/1.2
maxp Con 60 'Max pressure reading of 60 Pa, random max pressure that can be changed

'main loop

main:

Pauseus 100 'check sampling time for that of the sensor and the pic to see if this value is correct

P = maxp * ad_word / 1023 'equation to calculate pressure using the variables and constants defined earlier
'Also contains 10 bit results
'Hopefully will output whole value without truncation, if it does find value to multiple by
X = 2 * P / 1.2

V = SQR X 'calculating velocity with the sqaure root of 2 times pressure (p) divide by density (1.2)

LCDOUT \$FE, 1, "V"

Pause 100 'unsure of the pause and if this will show the dynamic change in airspeed

Goto main

End
But, now I am getting an error. I believe it is with one of my eqautions but I am unsure why. The error I am getting is....

Executing: "C:\pbp\PBPW.EXE" -ampasmwin -oq -z -p16F88 "airsp.bas"
PICBASIC PRO(TM) Compiler 2.50b, (c) 1998, 2008 microEngineering Labs, Inc.

U:\WINDTUNNEL\AIRSPEED PROJECT\AIRSP.BAS ERROR Line 46: Syntax error.Halting build on first failure as requested.
BUILD FAILED: Wed Nov 10 12:28:39 2010
Any help?

Thanks!!

-Marcus

15. Or, here is this to make it easier to read.

Code:
``` 'Using PIC16F88
'Identify and set the internal oscillator clock speed (required for the PIC16F88)

'Using configuration bits of the following
'Oscillator: INTRC-OSC2 as RA6
'Watchdog Timer: ON
'Power Up Timer: ON
'Code Protect: Off
'RA5/MCLR pin function select: RA5 (to use this pin as extra I/O instead of MCLR)

DEFINE OSC8
OSCCON.4=1
OSCCON.5=1
OSCCON.6=1

'Turn on and configure AN4 (A/D convertor on pin 3)

ANSEL.4=1 : TRISA.4=1			'sets up the A/D conerter on RA4/AN4 (pin3) and sets it to an input
ADCON1.4=1				'have 10 bits be right justified
DEFINE ADC_CLOCK 3				'Sets clock to internal oscillator
DEFINE ADC_SAMPLEUS 10			'Pause for sampling, I don't actual use this anywhere in the program

'Initialize I/O pins
TRISB=0						'Set PORT B pins to all outputs
TRISA=%00010000					'Set PORT A pins to output except for RA4/AN4(pin 3), it will be set as an input

'Declare variables

ad_word		                Var		Word		'Word from the A/D converter (10 bits padded with 6 0's)
P			Var		Word		'P is the calculated pressure variable from the reading of the pressure sensor
V			Var		Word		'V is the calculated airspeed from the pressure value
X			Var		Word		'X is a variable taking place of the calculation 2*9/1.2
maxp		                Con		60		'Max pressure reading of 60 Pa, random max pressure that can be changed

'main loop

main:

Pauseus	100		'check sampling time for that of the sensor and the pic to see if this value is correct

P = maxp * ad_word / 1023	'equation to calculate pressure using the variables and constants defined earlier
'Also contains 10 bit results
'Hopefully will output whole value without truncation, if it does find value to multiple by
X = 2 * P / 1.2

V = SQR X					'calculating velocity with the sqaure root of 2 times pressure (p) divide by density (1.2)

LCDOUT \$FE, 1, "V"

Pause 100					'unsure of the pause and if this will show the dynamic change in airspeed

Goto main

End```

16. Hello Marcus,

I suspect your error is here as we only get integer math:
Code:
`	X = 2 * P / 1.2`
Code:
`	X = 20 * P / 12`
Best Regards,
Paul

17. Thanks, Paul!

I'll give that a try when I am in lab tomorrow morning. I also got my op amps today so hopefully I can get my pitot and up running tomorrow!

18. Paul, that fixed the problem. Thanks again.

Hopefully this all works as planned now!

19. Hello Marcus,

No problem, that was an easy one. Dave (and you) did the hard part of the work. I'm glad you have it working!

Best Regards,
Paul

20. I am glad your code works. But in case you will need one decimal place precision in your calculation, then you can re-work your formula in this way:

Code:
```Vu  var byte ' unit
Vd var byte  ' decimal

P = 6000 * ad_word / 614
V = SQR(P)
Vu = V DIG 1
Vd = V DIG 0

LCDOUT \$FE, 1, Vu,".",Vd```
Cheers

Al.
Last edited by aratti; - 11th November 2010 at 14:59.

21. Fellas,

I am having a problem with my LCD display that I can't seem to figure out what the deal is. I have a 16 x 2 LCD that has a Hitachi 44780 driver. I am having problems with the value it is reading being displayed in a useable number.

Sitting at "idle" the LCD outputs 00008, which is fine. But then when the values increase it gets up to 00010 and then roles back around to 00001 and can do that for several cycles up and down. What is it doing? It should be outputting a velocity in relation to the pressure.

My basic LCDOUT command is as follows

Code:
```LCDOUT \$FE, 1,"Begin Program"

Pause 2000

'main loop
main:

Pauseus	200						'check sampling time for that of the sensor and the pic to see if this value is correct

P = maxp * ad_word / 1023	'equation to calculate pressure using the variables and constants defined earlier
'Also contains 10 bit results
'Hopefully will output whole value without truncation, if it does find value to multiple by
Pauseus 200

X = 20 * P / 12

Pauseus 200

V = SQR X					'calculating velocity with the sqaure root of 2 times pressure (p) divide by density (1.2)

Pauseus 200

LCDOUT \$FE, 1

LCDOUT \$FE, \$80 + 4, dec5 V			'Output Velocity to LCD, should be in m/s

Pauseus 200

Goto main

End```
Any thoughts?

You are all great and I am so thankful for all the help you guys are giving me!

-Marcus

22. Insert the following snippet to stabilaze the ADC reading averaging it.

Code:
```A0 var Byte

For A0  = 0 TO 7
Pauseus	200
Next A0

Al.

23. Hi, Marcus

One thing hurts me :

you use a 500 kPa sensor ...

but @ reasonnable ( flying ) speeds ... say @ 90m/s = 324 km/h ...

the diff pressure only is 6k Pa ...

1/100 of your sensor full scale !!! - or 10 units of the ADC.

Adding the noise produced by the sensor ( see Freescale ANs about it ) - even if amplified - you do not measure anything real ...

a 50 kPa range sensor would allow you to measure close to speed of sound !!!

No need to calculate average value ... it's noise average value you measure ...

In short words ... you can't succeed in this way ...

first choose a sensor to match your measured speed range.

Alain

24. Alain since the OP is is using a 1.2 factor for fluid density, it means that he is not working with air, but the gas he is using is more dense than the air.

Cheers

Al.
Last edited by aratti; - 12th November 2010 at 23:49.

25. As an example, using the ISA standard sea level conditions of P = 101325 Pa and T = 15 deg C, the air density at sea level, may be calculated as:

D = (101325) / (287.05 * (15 + 273.15)) = 1.2250 kg/m3
Above is from
http://wahiduddin.net/calc/density_altitude.htm

26. D = (101325) / (287.05 * (15 + 273.15)) = 1.2250 kg/m3
Dave you are correct, fluid density is temperature dipendent. I made a wrong assumption, Alain forget my previous post.

Al.

27. Thank you all for the help.

I'll explain to all of you what this is all for. What I am have been building this semester is a open circuit wind tunnel for a mechatronics class. We have several criteria that it has to meet, which I will spare you the details of. But, the basic set up I have at the moment is that I have a DC motor spinning an RC plane prop to create the wind with a PWM function off of a PIC16F88. We are using a keypad to control the different speed settings and LED's to display the speed setting for the keys pressed. Then we have another PIC16F88 running a pitot tube set up which consist of a differential pressure sensor, op amp, voltage regulators, PIC16F88, and then an LCD for outputting displays and for helping as a "heart beat" monitor. We had a deadline coming up this Tuesday for an extra %10 on the project if we had everything function. I got it all locked down tonight and should be set for the deadline.

Alain - I realized when I started the programming for the sensor last week that I had one that was WAY over sized for what I was using it for. I got it as a sample and am happy it has gotten me to where it has, but I am planning on ordering a more realistic one next week for the final presentation. Realistically I only need one that hits 1 psi because I am only planning on hitting 60 mph wind speeds. Its a matter of finding one that can give me what I want without the high cost.

Al - We are indeed working with air and yes 1.2 is the density of air. That is even straight from my fluid dynamics text book.

Again, thank you all for the help! I have most of the stuff completely ironed out except for calibrating of the pitot tube (probably need a better pressure sensor ). But now with the month left in the project it leaves me the chance to add in safety features such as a open door sensor, tachometer, refine the pitot tube setup and possibly a data acquisition set up.

I doubt I can help many people on here with any programming, but I do have a lab book that has examples for PWM and other simple functions to fun things. Let me know if there is ever anything I can help with.

-Marcus

You do not have permission to view the list of names.