Measure wind speed with a 3D-printed anemometer

Print a cup anemometer that spins on the kit's DC motor, count its turns with the photo-interrupter and turn them into a wind speed in km/h.
  • Level:Intermediate
  • Duration: 1 h 10 min
  • Ages 11+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Measure wind speed with a 3D-printed anemometer – EEMENTOR STEM™ lesson

Weather stations measure wind speed with a cup anemometer: three or four cups on arms that the wind spins round. The faster the wind, the faster it turns. In this lesson you print one, count its turns with the photo-interrupter and turn the count into km/h. You also learn about interrupts, a way for the UNO to notice very short events even when it is busy doing something else.

What you'll learn

  • How to count fast pulses with an interrupt
  • How to turn pulses into turns per second, and turns into a speed
  • Why measuring instruments need calibrating
  • How a slotted disc, called an encoder disc, measures rotation

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • Photo-interrupter module (45-in-1 Sensor Kit)
  • 3–6 V DC motor, used only as a bearing (UNO R3 Starter Kit)
  • 3 female-to-male jumper wires
  • A fan or a hair dryer on its cold setting to test with
  • The printed parts from the 3D printing box below (disc, cups and mast), or the cardboard version described there
  • Breadboard and jumper wires (UNO R3 Starter Kit)

Wiring

Breadboard wiring diagram: Measure wind speed with a 3D-printed anemometer
Breadboard view. Check each connection against the wiring table below.
From To
Photo-interrupter S UNO pin 2
Photo-interrupter + 5V
Photo-interrupter − GND
DC motor Not connected

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

The sensor must be on pin 2 or 3: those are the two UNO pins that can trigger an interrupt.

The sketch

const int SENSOR_PIN = 2;
const int SLOTS = 4;                 // windows in the rotor's disc
const float CUP_RADIUS = 0.05;       // metres from the shaft to the middle of a cup
const float FACTOR = 2.5;            // wind speed / cup speed; set it when you calibrate

volatile unsigned long pulses = 0;
volatile unsigned long lastPulseUs = 0;

void countPulse() {
  unsigned long now = micros();
  if (now - lastPulseUs > 2000) {    // ignore bounces shorter than 2 ms
    pulses++;
    lastPulseUs = now;
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(SENSOR_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), countPulse, RISING);
  Serial.println("turns/s\tkm/h");
}

void loop() {
  delay(1000);                       // count for one second

  noInterrupts();                    // copy and reset the counter safely
  unsigned long count = pulses;
  pulses = 0;
  interrupts();

  float turnsPerSecond = (float)count / SLOTS;
  float cupSpeed = turnsPerSecond * 2 * PI * CUP_RADIUS;   // metres per second
  float windKmh = cupSpeed * FACTOR * 3.6;

  Serial.print(turnsPerSecond, 2);
  Serial.print("\t");
  Serial.println(windKmh, 1);
}

Test and calibrate

  1. Upload the sketch, open the Serial Monitor at 9600 baud and turn the rotor slowly by hand. Every quarter turn adds one pulse.
  2. Blow on the cups or hold the anemometer in front of a fan. Open Tools → Serial Plotter to see the speed as a graph.
  3. To calibrate, you need a known wind. On a calm day, an adult can hold the anemometer out of a car window (passenger side, never the driver) at a steady 10, 20 and 30 km/h on a quiet road. Compare the readings with the car's speed and change FACTOR until they match.
  4. Real anemometers are calibrated in a wind tunnel. Without one, your readings are a good estimate, not an exact value.

How it works

An interrupt makes the UNO stop whatever it is doing the moment pin 2 goes from LOW to HIGH, run countPulse() and then carry on. That way no pulse is missed, even during delay(). Variables that an interrupt changes are marked volatile, and the main loop switches interrupts off for a moment while it copies and resets the counter, so the number can't change halfway through.

Each turn of the rotor gives 4 pulses, because the disc has 4 windows. The middle of each cup travels round a circle of 2 × π × 0.05 m = 0.31 m per turn. The wind moves faster than the cups, because the cups also catch some wind on their back side; for cup anemometers the wind is usually 2 to 3 times faster than the cups. That is the FACTOR.

Try this next

  • Show the speed on the 1602 LCD, with the highest gust since you switched on.
  • Convert km/h to the Beaufort scale (0 to 12) and print names like "fresh breeze".
  • Move it to the ESP32 and send the wind speed to ThingSpeak, like in the cloud weather logger.

Troubleshooting

  • The count doesn't change: watch the module's LED as you turn the rotor slowly. If it never changes, the disc doesn't pass through the middle of the slot; move the module.
  • Far too many pulses: the disc wobbles and touches the slot. Push the rotor straight onto the shaft, or make the 2000 in countPulse() bigger.
  • It only spins in strong wind: the motor's brushes add a little friction. Spin it by hand for a minute to run it in, and keep the cups clean of strings.
  • A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

45-in-1 Sensor Kit | Compatible with Arduino IDE and ESP32 $37.00

Shop the kit