Monday, 30 May 2016

The acoustic sensors and their limits

by Giovanni Carrera rev. 30/05/16
Ultrasonic ranging modules as the HC-SR04 are widespread in the electronics and amateur robotics, but it is also important to know the limitations of these sensors and the possible improvements of their accuracy. Before introducing the measurement circuits and firmware, I dedicate a space to the speed of sound and its propagation.

The speed of sound in air

The sound waves propagate in a medium by means of oscillatory displacements of its particles, around the rest position and along the direction of propagation of the wave. The vibratory movements are transmitted to neighboring particles and so on. The speed of propagation of sound waves depends on the density of the medium, so it is almost nothing in the vacuum and maximum in metals. The acoustic waves are generated by a source, whose geometrical dimensions are in some way related to the wavelength, therefore the inverse of the frequency generated. For this reason, the speakers used for the bass of a stereo system are considerably larger compared to ultrasonic transducers.
If we know the propagation velocity v we can calculate the wavelength l, the space occupied by a cycle:
v = space/time = l/T = l×Þ  l = v/f
Indicating with T the period of the oscillations of the particles, i.e. the duration of a wave cycle and the inversion of the frequency (T= 1 / f).
In the case of a source from 40 kHz ultrasonic, like that used, the wavelength is:
l = 344/40000 = 8.6 [mm]
For a distance meter, the wavelength is very indicative, since it gives an idea of ​​the spatial resolution and the size that the objects must have to reflect these waves, that is, much larger thanl. These concepts are very similar to those of the radar, which uses electromagnetic waves instead of acoustic waves. The wavelength for typical nautical radar is about three centimeters. Using acoustic waves at higher frequency would create problems because of the greater absorption and therefore require significant peak powers of the transducers, which are currently of the piezoelectric type. Also the echo sounder has the same problem: to be able to detect small targets, such as fish, the frequency must be increased from 30kHz, for bathymetry, to 400kHz for fishing, knowing that the speed of sound at sea is about 1500 m/s, the respective wavelengths are: 5 and 0.375 cm.
Unlike marine transducers, there are major problems in the air, due to the worst acoustic coupling of the transducer in the air with respect to water.
The speed of the acoustic waves is not constant, but depends on various factors such as temperature, humidity and atmospheric pressure in the environment in which it operates. The most significant is the temperature; a linear approximate formula is as follows:
v » 331.45 + 0.6  Tc   (1)
Where Tc is the temperature in degrees Celsius. The previous formula is derived from the linearization of  this more accurate expression:

·        R = universal gas constant = 8.314 [J/(mol×°K)]
·        T= absolute temperature in Kelvin degrees [°K]
·         g = adiabatic constant of gases
For dry air, g = 1.4 and M = 0.02895 [kg /mol], grouping constants, we obtain:

From which we see the dependence of the speed with the square root of the temperature, expressed in Kelvin degrees. For modest temperature variations do not have large differences, as we can see in figure 1.
Figure 1 - Speed of sound versus temperature.
For our application, we can use the linear formula (1), this is because we don’t expect large changes in temperature. Not having the information of the ambient temperature, it is hypothesized that this is fixed: Tc = 20 °C, so v = 343.85. In this case the percentage error on speed is visible in the following table:

T [°C]

In our case, making a measurement, in summer, at 35°C, we have an error of almost 10 cm at full scale (400). Measurements more accurate require a temperature sensor to correct the speed.
Even the air humidity and the pressure modifying the speed of sound: from 50% to 80% relative humidity it has a speed increase of about 1.1% to 101,325 kP atmospheric pressure. The figure 2 shows the variation of speed with relative humidity at various ambient temperatures in Celsius degrees. You may notice that the humidity influence is most evident at high temperatures, as could be expected.

Figure 2 - Speed of sound in air

All the considerations previously views lead to say that the distance measurements based on the detection of the time of flight (TOF) with ultrasound have an accuracy around the centimeter, if corrected with the ambient temperature.
Recent techniques are based on measurement of the phase between continuous wave transmitted and received (Binary Frequency Shift Keyed-or BFSK). With these techniques, using an FSK modulation with frequencies of 40 and 41 kHz, we can achieve  an accuracy of the distance measurement below the millimeter. This greater accuracy is paid with a considerable complexity of electronic circuits and a higher energy consumption, because we have to generate a continuous wave. An alternative is to use a laser rangefinder.

The HC-SR04 sensor

Figure 3 - The HC-SR04 module.
This sensor, which typical aspect is seen in Figure 3, is simple and economical. It has only four pins:

+5v Power supply input
trigger (TTL input)
Measurement (TTL output)
Common ground

The module has a microcontroller that, when the trigger pulse is received (10μs min), send a burst of 8 pulses at 40 kHz. A MAX232 is used as driver for the Tx transducer in order to elevate the driving voltage to approximately +/- 10V. The return echo, received by the Rx transducer, is amplified by an LM324 and processed by the microcontroller that generates an output pulse which duration Dt is proportional to the target distance. It corresponds to the time that elapses between the emission of the burst and the instant at which it receives the echo, also called TOF. The timing diagram shows the sequences described.
Figure 4 -Timing diagram.
It follows that the distance Dt will be proportional to the length of the output pulse according to the expression:
The period Dt must be divided by two because it includes the time for the reflected wave return. This applies to the sonar, echo sounders and radars, which use the propagation time to detect distances.
In our case, expressing d in [cm] and Dt in [µS], we get:
d =  ΔT / 58.165 [cm]
The measurement range of this sensor is from a minimum of 2 cm to a maximum of 400, measured in microseconds the Dt, these limits correspond to 116 µs (2cm) and 23266 µs (400cm). With a system like Arduino it is very easy to measure these times because there is a specific and powerful function.

Teensy (or Arduino) interface and program

Four wires are required for the connection to Teensy, as shown in figure 4. Changing only the signal pins, any Arduino board or compatible can be used for this application, I used a rev.3.1 Teensy interfaced with a LCD display. The figure 5 shows the wiring diagram for my board.
Figure 5. - Wiring diagram for Teensy board.
As shown, the pin 22 of Teensy is connected to the Trigger and pin 23 to Echo.
The code does not require much effort, I add the definitions:

#define Trigger 22 // Trigger Pin
#define Echo 23 // Echo Pin
long duration, distance;

In the main loop it creates the trigger pulse and then uses the pulseIn for Echo pulse duration:

digitalWrite(Trigger, HIGH);
digitalWrite(Trigger, LOW);
duration = pulseIn(Echo, HIGH);
distance = duration/58.165;
A good choice for pulseIn is to use a third parameter:
pulseIn(pin, value, timeout)
As default timeout = 1e6 microseconds, in our case, we might ask timeout = 23266, corresponding to 400cm away. The function returns zero if timeout, or over range.
In the remaining of the program there are instructions for printing on the LCD display the distance measurement.
It would be advisable to check the distances with calibration measurements: placing the sensor at known distances from a flat wall, taking care to position the transducer axis perpendicular to the wall. With three or four measures you can make a good calibration.
As described earlier, a significant improvement of the system is to measure also the temperature. There are several temperature sensors for Arduino; some have the analog output, as the LM35 which has a linear output with a scale factor of approximately 10 mV/°C. Since Arduino has a 10-bit ADC, with full scale of 5 V it would be possible to obtain a resolution of approximately 0.5 °C, more than good for the compensation of the temperature using the formula (1). A more economic system, which requires a better calibration, is to use a thermistor, i.e. a resistor that varies its resistance with temperature. In the web there are many applications of this type.

1.      “HC-SR04 User's_Manual”, Cytron Technologies, May 2013.
2.      “Speed of sound”,
3.      “A high accuracy ultrasonic distance measurement system using binary frequency shift-keyed signal and phase detection”, S. S. Huang, C. F. Huang, K. N. Huang and M. S. Young, REVIEW OF SCIENTIFIC INSTRUMENTS VOLUME 73, NUMBER 10 OCTOBER 2002.

4.       “LM35, Precision Centigrade Temperature Sensors”, National Semiconductor, November 2000

Sunday, 29 May 2016

An isolated analog input for Arduino

by Giovanni Carrera, rev. 28/05/16
A voltage to frequency converter can realize an opto-isolated analog input for Arduino or other microcontroller systems. This circuit is particularly suitable for industrial control plants with 4-20mA sensors.


The signals from field sensors can be affected by noise generated by power surges, lightning strikes or other EMI (Electromagnetic Interference) sources and also by ground potential differences. One method to avoid most of these problems is to use a complete isolation from the field.
The isolation of an input sensor will require a separate power supply to power the field device and the circuit that realize the insulation itself.
In the 80s, when the microcontrollers hadn’t  digital to analog converters (ADC) integrated, I had designed a system with voltage to frequency converters to achieve high-resolution analog inputs and an easy true isolation with the field sensors.  Only drawback was the low sampling rate, but usually high frequencies aren’t required in industrial plants.
The following figure shows a three channels board that I designed many years ago for a 6502 control system.

Figure 1 - A three analog isolated channels VFC board

The circuit

So I think up to use this circuit also with Arduino. The diagram of Figure 2 shows the circuit that accepts an input voltage from about 20mV to 5V or a current of 4 to 20 mA (with the jumper W1 inserted). The two resistors in parallel R2 and R3 give a value of about 250 ohms, in order to have 1V to 5V for 4mA to 20mA input.
Just three wires and a resistor are required to connect the circuit to the Arduino Uno. The output of the opto-coupler should be connected to the digital input D5 with a pull-up 2.2kW resistor connected to the +5V of Arduino.
Figure 2 - Schematic of the circuit.
If an input range of 10V is required, a 15V power supply is necessary, so you have to change the 7808 regulator with a 7815.
The resistor R10 reduces the switching time of the phototransistor.
The circuit of the converter is obtained from the datasheet of the LM331.
The output frequency is:
Fout = Vin*(R6+P1)/(2.09*R4*R7*C3)
This circuit, with the values used,  has a conversion factor of about 1kHz/V.
The duration of output pulses is:
T = 1.1* R7*C3 = 74.8 [ms]

Hardware components

1x Arduino board

Passive components

R1= 100kW ±1% metal film
R2= 3.3kW ±1% metal film
R3= 270W ±1% metal film
R4= 100kW ±1% metal film
R5= 47W ±5%
R6= 12kW ±1% metal film
R7= 6.8kW ±1% metal film
R8= 10kW ±5%
R9= 330W ±1% 1/4W
R10= 220kW ±5%
P1= 5kW multiturn

C1= 100nF Mylar
C2= 1MF Mylar
C3= 10nF Mylar
C4 = 100nF ceramic AVX
C5 = 4.7 MF Electrolytic
C6= 220 MF Electrolytic
T1=230V (or 115V), 12V, 1VA transformer

Active components
U1= LM331
U2= LM7808
Pd1= 4x1N4001

Calibration and measurements analysis

A very stable power supply, as source, a frequency counter and an oscilloscope are been used for testing the circuit.
The 13 measurements were analyzed with a spreadsheet using a linear regression and the results were very good, as you can see from the figure below graph.
Figure 3 – Calibration curve of the circuit.
As you can see from the formula of the regression line, the correlation coefficient is equal to one, using six decimal digits.

Arduino interface and program

Arduino can measure the frequency in two ways:
·        period measurement, using the pulsein() function;
·        frequency measurement, with CPU Timer/Counters , using special libraries.
The first method uses twice the function pulsein() in order to measure the HIGH time and LOW time of the signal, with a microsecond resolution. The sum of the two measurements is the period of the signal. For a 5kHz signal, the period is 200 µs = HIGH time + LOW time = 125+75 µs. The time resolution is  relatively low and the accuracy of measurement is also affected by the time of the program instructions.
The positive aspect about this method is the measurement speed which is slightly higher than the measured period. At a disadvantage, in addition to the less accuracy, it is most sensitive to the electrical grid noise (50 or 60Hz).
For these reasons, I prefer a frequency measurement with respect to the period. The measurement time is higher but you get a higher precision and precise sampling times. In addition, choosing a measurement period multiple of that of the electrical grid, it has excellent noise immunity.
I use the FreqCounter library by Martin Nawrath KHM LAB3:
This library uses Timer/Counter1 for counting pulses on rising edge of T1/PD5/digitalPin5 and Timer/Counter2 for the gate-time generation with 1 ms interrupts.
I chose a gate time equal to 1000 ms to mediate the count on a period of 50 or 60 mains cycles. In this case you get a resolution that is five times greater than that of Arduino Uno.
The Arduino sketch of the following example is very simple:

#include <FreqCounter.h>

void setup() {
  Serial.begin(9600);  // connect to the serial port
  Serial.println("Optoisolated analog input");

long int frq;
void loop() {

 FreqCounter::f_comp= 0;   // Set compensation to 0
 FreqCounter::start(1000);  // Start counting with gatetime of 1000ms
 while (FreqCounter::f_ready == 0)   // wait until counter ready

 frq=FreqCounter::f_freq;   // read result
 Serial.println(frq);       // print result

By comparing the frequency meter readings with the values transmitted by Arduino I found only small differences and the error is very good, as shown in the following table.
Meter [Hz]
FreqCounter [Hz]
Error %
With appropriate libraries and with other CPU, you can have multiple frequency inputs and then various isolated analog channels.

1.      “LMx31x Precision Voltage-to-Frequency Converters”, Texas Instruments, SNOSBI2C –JUNE 1999–REVISED SEPTEMBER 2015.

2.      “Arduino Frequency Counter Library”, Laboratory for Experimental Computer Science at the Academy of Media Arts Cologne,