Freesteel Blog » Ultrasonic distance sensor as a sonic anemometer

Ultrasonic distance sensor as a sonic anemometer

Tuesday, September 8th, 2015 at 4:08 pm Written by:

The amazingly cheap HC-SR04 ultrasonic sensor works pretty well for what it does, which is measuring distances by echo location, but I wanted to use it for measuring air velocity as my mechanical anemometer is unreliable and of no use for getting the direction.

The sonic anemometer uses the theory that you can measure the time it takes for sound to travel through the air (about 2938.6microseconds to travel one metre) and the delay it would experience if the air was also traveling against the direction of the sound waves (about 8.6 additional microseconds for each metre per second in velocity). These values should be no problem for an Arduino running at 16MHz frequency to detect.

The basic interface code to run the HC-SR04 is as follows:

float speedofsoundmps = 340.29; // metres-per-second
digitalWrite(triggerpin, LOW);  
digitalWrite(triggerpin, HIGH);
digitalWrite(triggerpin, LOW);
long timemicros = pulseIn(echopin, HIGH);
System.out.print("Distance (cm) = ");
                       // factor 2 because distance
                       // is there and back

The basic code for pulseIn() counts processor cycles for the duration of the voltage being HIGH.

Here’s my experimental setup using two such devices, one sending and the other receiving (though you do need to trigger both in order to arm the receiver). Note the desktop fan to generate the wind.

And these are the experimental results plotted over five minutes, making a reading 20 times a second for ten minutes.
The average time of 1545.7microseconds equates to 52cms, which is an under-reading as the actual distance is 60cm, but we’ll ignore that for now.

If we turn the fan on we get an average reading of 1551.7micoseconds with a higher standard deviation of 13.4 (not surprising as the fan air is chopped and turbulent) which is an average difference of 6microseconds amounting to a wind speed of about 2 metres per second, agreeing approximately with the figure from my mechanical anemometer.

I’m not interested in tracking down the source of the error or calibrating this setup while the readings themselves are so darn noisy and in excess of the signal I am attempting to detect.

What is the source of the noise?

The clue is in the fact that there are two peaks in the readings at around 1540ms and 1560ms.

Here is the measurements from the experimental setup, using a very good digital oscilloscope.
Blue is the trigger, yellow is the echo, and the vertical white lines are 5microseconds apart, meaning that our pulses are 50microseconds apart (count them) or 20 times a second.

If we zoom in at the start of one pulse, we can see that the start of the echo pulse (whose length pulseIn() measures the duration of) doesn’t begin till around 460microseconds after the trigger pulse. (The duration is the length of time this pulse stays HIGH after it has gone HIGH.)

We can zoom in pretty close to that upswing moment of that echo signal, where D=460microseconds and the horizontal increments are 10microseconds.

Zoom in even closer with horizontal increments of 500nanoseconds. Note a little bit of signal noise leaking into the cyan trigger pin voltage.

And here’s the really great feature: We can take the average over 64 signals to see what appears to be a constant probability distribution within a range of exactly 5microseconds for when the signal goes high.


I wonder what’s happening at the other end of the graph when the echo signal goes down?

Here’s the super-imposed plot with 200miliseconds of persistence:


The signal goes LOW at around 2233microseconds. Don’t forget to subtract the initial 460microseconds from the consistent delay of the signal going HIGH to get 1773microseconds which, if you multiply out by the speed of sound gives 60cm, which is exactly the right distance, indicating that the source of the error could be the pulseIn() function.

And the average of the output signals has a stepped appearance with flat steps of 20microseconds and slopes 5microseconds wide.

Just to make sure the pattern wasn’t due to the chopped air from fan, I tried it out with a vacuum cleaner pointed into a tube.


Further investigations and searching on the interwebs reveals that someone with much better hardware-foo has reversed engineered this device and upgraded it.

In appears that 460 microseconds initial delay is merely the charging time for the MAX232A, which generates the signal, to charge itself up in order to run the transducer that makes the sound at +-10V.

Also, the plots detailing the 40kHz sound signal leaving the transducer produces a wavelength of about 25microseconds.

Where have I seen that number before?

He writes:

The circuit has 2 transducers one for emission and one for reception.

To transmit the ultrasonic pulses a relatively high voltage is needed. A MAX232 is cleverly used to produce +/-10V from 5V. The transducer is connected between two outputs so it is in fact powered at 20V. Power is only applied to this circuit some time before and during pulse emission because the internal switching charge-pump is noisy.

When the circuit switches to receive mode the MAX232 power is cut off. The receive and emit circuits are controlled by an EM78P153S chinese microcontroller running at 27MHz.

The receiver side uses LM324 which contains 4 OPAMPs. U2D is just a times 6 amplifier. U2C is a multiple feedback (1st order) pass band filter which is followed by another times 8 amplifier (U2B). The last OPAMP (U2A) is used together with Q1 as a hysteresis comparator…

There are several problems with this circuit. First the microcontroller uses polling to detect a return pulse. This can be observed because sometimes only the second pulse is detected…

He then details plans for desoldering and replacing several of the surface-mounted components onto a new board and new ATTiny microcontroller to improve its performance.

In summary, the steps are due to skip/slipping the first or second wave length of the incoming signal and the further noise is due to the timing cycle within the onboard microcontroller.

For my purposes, I think I’d have to detect the individual waves of the echo signal and do some averaging of the phase shift encoded in the first eight of them to get an accurate enough measurement.

Too hard for me at the moment, unless I can totally avoid messing around with any of that complicated OPAMP nonsense about which I am completely ignorant.



  • 1. cem replies at 19th March 2016, 3:42 am :

    Hi Julian nice work,
    I have been working on the same project.
    I want to know how did you talk 2 HC-SR04’s? One as sender other as receiver?

  • 2. Julian replies at 23rd March 2016, 10:31 am :

    Yes. But you have to trigger both of them to get the receiver to start listening. Then you have to tap into the sender to record the exact moment the signal gets sent.

    More details here:

    Feel free to ask questions.

  • 3. jack dawson replies at 16th January 2019, 6:05 am :

    Usually, the frequency of the ultrasonic anemometer is mainly 200 KHz probe, and there are 4 detectors. Through the description in this paper, it is uncertain whether the wind speed of a large range can be monitored.

    Refer to this article:

    This covers almost all the principles of wind monitoring, and I hope it will be helpful to you.

  • 4. Saptha Ss replies at 1st May 2019, 11:33 am :


    i tried the same thing with one hcsr04..its transmitter and receiver in face to face position..but when i start the measurement time of flight remains the same…its independent of wind speed(from the table fan).but m getting the distance accurately.

  • 5. Julian replies at 1st May 2019, 12:10 pm :

    Did you tap in to the outgoing signal like I showed here?

    The problem is that the sound pulse doesn’t go out a predictable time after you send the trigger signal. There can be anything between a 0 and a 4 microsecond delay. That’s why you need to detect the exact moment with a second wire.

    Then use that pulse (the real time of the signal) to set the trigger on the oscilloscope so that the response signals are all aligned.

    If you get somewhere, I’d like to know how well it works.

  • 6. Nour replies at 30th May 2021, 2:46 pm :

    Hi Julian;
    i am working on my final year project master,could you please share the Arduino code because its not working here

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>