Built-in project · Arduino Uno R3

Pitot airspeed meter on an Arduino Uno

An MPX5010DP differential pressure sensor on a pitot tube and a 16x2 I2C LCD: the wind’s pressure in pascals and the airspeed it means, in m/s and km/h. The whole build, an Arduino Uno and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 20 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $49. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • How a pitot tube turns airspeed into pressure
  • Bernoulli's equation for speed from pressure
  • Zeroing a sensor with no input
  • Averaging analog readings
  • Why small speeds are hard to measure
  • Difficulty: Intermediate
  • Time: About 20 minutes
  • Board: Arduino Uno R3
  • Parts: 4

How it works

A pitot tube has a tip that faces the wind and holes on its side. The tip gets a higher pressure than the side holes, and that difference grows with the square of the airspeed. An MPX5010 differential pressure sensor measures the difference and outputs a voltage on A0.

At power on, with no wind, the sketch averages 32 readings and stores that as its zero. Then it repeatedly converts the voltage to pascals, and the pressure to a speed with the density of air. The LCD shows pascals on the first row and speed in m/s and km/h on the second.

Parts list

4 parts, plus the jumper wires. They retail for about $49; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Pressure sensor, MPX5010 / MPX5700 pin VSArduino Uno R3 pin 5V
Character LCD with I2C backpack pin VCCArduino Uno R3 pin 5V
Pressure sensor, MPX5010 / MPX5700 pin GNDArduino Uno R3 pin GND
Character LCD with I2C backpack pin GNDArduino Uno R3 pin GND
Pressure sensor, MPX5010 / MPX5700 pin VOUTArduino Uno R3 pin A0
Character LCD with I2C backpack pin SDAArduino Uno R3 pin A4
Character LCD with I2C backpack pin SCLArduino Uno R3 pin A5

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Pitot airspeed meter: an NXP MPX5010DP differential pressure sensor on a
// pitot tube, and the airspeed on a 16x2 I2C LCD.
//
//   A0      the MPX5010DP's VOUT (pin 1; pin 2 GND, pin 3 VS on 5 V)
//   P1      the pitot tube's tip, facing the wind (the marked side's port)
//   P2      the static holes on the side of the tube
//   LCD     SDA -> A4    SCL -> A5    VCC -> 5 V    GND -> GND
//
// The air rammed into the tip is at a higher pressure than the air sliding
// past the side holes, by half the air's density times the speed squared
// (Bernoulli). The sensor reads that difference:
//
//   VOUT = VS x (0.09 x P + 0.04)      P in kPa, 0 to 10 (the datasheet)
//
// so the sketch works in fractions of the supply, which the Uno's converter
// measures against too. A real part's zero can be anywhere from 0 to 0.425 V,
// so the sketch measures it at power on, with no wind, and subtracts it.
//
// One converter step is 10.9 Pa: about 4 m/s at the bottom of the scale and
// a fraction of a m/s at 30 m/s, which is why pitot tubes read nothing at a
// walking pace.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

const float AIR_DENSITY = 1.204;    // kg per cubic meter, 20 C at sea level

LiquidCrystal_I2C lcd(0x27, 16, 2);
float zero = 0.04;                  // the fraction of VS at no pressure

float readFraction() {
  long sum = 0;
  for (int i = 0; i < 32; i++) sum += analogRead(A0);
  return sum / 32.0 / 1023.0;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: pitot airspeed meter");
  lcd.init();
  lcd.backlight();
  lcd.print("Zeroing...");
  delay(100);                       // the sensor's 20 ms warm up, and more
  zero = readFraction();
  Serial.print("Zero: ");
  Serial.println(zero * 5.0, 3);
  lcd.clear();
}

void loop() {
  float kpa = (readFraction() - zero) / 0.09;
  float pa = kpa * 1000.0;
  if (pa < 0) pa = 0;
  float speed = sqrt(2.0 * pa / AIR_DENSITY);  // m/s

  lcd.setCursor(0, 0);
  lcd.print(pa, 0);
  lcd.print(" Pa        ");
  lcd.setCursor(0, 1);
  lcd.print(speed, 1);
  lcd.print(" m/s  ");
  lcd.print(speed * 3.6, 0);
  lcd.print(" km/h  ");

  Serial.print("Pa: ");
  Serial.print(pa, 0);
  Serial.print("  m/s: ");
  Serial.println(speed, 1);
  delay(250);
}

Code walkthrough

The key functions of the sketch, and what each one does.

readFraction sketch.ino

Takes 32 analogRead samples on A0, averages them and divides by 1023. The answer is a fraction of the supply voltage, which suits the sensor, since its output is also given as a fraction of the supply.

float readFraction() {
  long sum = 0;
  for (int i = 0; i < 32; i++) sum += analogRead(A0);
  return sum / 32.0 / 1023.0;
}

setup sketch.ino

Starts serial and the LCD and shows Zeroing. After a 100 ms wait for the sensor to warm up, it stores a reading as zero. Keep the tube out of the wind during this, since that reading becomes zero pressure.

void setup() {
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: pitot airspeed meter");
  lcd.init();
  lcd.backlight();
  lcd.print("Zeroing...");
  delay(100);                       // the sensor's 20 ms warm up, and more
  zero = readFraction();
  Serial.print("Zero: ");
  Serial.println(zero * 5.0, 3);
  lcd.clear();
}

loop sketch.ino

Subtracts zero from a new reading and divides by 0.09 to get kilopascals, then multiplies by 1000 for pascals and sets negatives to 0. The speed is the square root of 2 times the pressure divided by AIR_DENSITY. It shows the results on the LCD and serial every 250 ms.

void loop() {
  float kpa = (readFraction() - zero) / 0.09;
  float pa = kpa * 1000.0;
  if (pa < 0) pa = 0;
  float speed = sqrt(2.0 * pa / AIR_DENSITY);  // m/s

  lcd.setCursor(0, 0);
  lcd.print(pa, 0);
  lcd.print(" Pa        ");
  lcd.setCursor(0, 1);
  lcd.print(speed, 1);
  lcd.print(" m/s  ");
  lcd.print(speed * 3.6, 0);
  lcd.print(" km/h  ");

  Serial.print("Pa: ");
  Serial.print(pa, 0);
  Serial.print("  m/s: ");
  Serial.println(speed, 1);
  delay(250);
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The meter shows a speed with no wind. This project
    There was pressure on the tube while it zeroed. Remove it from any airflow and reset.
  • Low speeds read as 0. This project
    That is normal. One converter step is about 10.9 Pa, which is roughly 4 m/s at the bottom of the scale.
  • A 3.3 V board gives clipped or damaged readings. Pressure sensor
    The output spans 0.2 to 4.7 V with a 5 V supply, which is above a 3.3 V ADC. Use a resistor divider and scale in code. The supply must be 5 V, about 4.75 to 5.25 V.
  • Pressure readings are wrong or reversed. Pressure sensor
    Know which port is which. The differential versions have two ports, and pressure on the vacuum side reads lower. Gauge parts compare to atmosphere. Convert volts to kPa using the datasheet transfer function.
  • The screen stays blank or shows only a row of blocks. Character LCD with I2C backpack
    The I2C address is usually 0x27 or 0x3F. Run an I2C scanner to find yours. Then turn the contrast trimmer on the backpack slowly until text appears.
  • The backlight is on but there is no text, or text is garbled. Character LCD with I2C backpack
    Wire SDA and SCL to the right pins (A4 and A5 on an Uno), power it from 5 V, and call lcd.init() and the backlight call in setup.
  • Upload fails or nothing runs after wiring pins 0 and 1 to a module. Arduino Uno R3
    Pins 0 and 1 are the USB serial port. Move the module to other pins, or unplug it while uploading. Also check the right board is selected.
  • Pins misbehave or the board resets when you power motors or servos from it. Arduino Uno R3
    Each I/O pin gives about 20 mA, 40 mA max. Power motors and servos from their own supply and join its ground to the Uno's GND.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.