Necessary knowledge: [HW] Controller module, [HW] User Interface Module, [AVR] Counters/Timers, [LIB] Timers, [LIB] Graphic LCD, [LIB] Sensors
Ultrasonic distance sensor determines the distance to an object by measuring the time taken by the sound to reflect back from that object. The frequency of the sound is somewhere in the range of ultrasound, this ensures more concentrated direction of the sound wave because sound at higher frequency dissipates less in the environment. A typical ultrasonic distance sensor consists of two membranes. One membrane produces sound, another catches reflected echo. Basically they are speaker and microphone. The sound generator generates short (the length is a couple of periods) ultrasonic impulses and triggers the timer. Second membrane registers the arrival of the sound impulse and stops the timer.From the timers time it is possible to to calculate the distance traveled by the sound. The distance to the object is half of the distance traveled by the sound wave.
The ultrasonic sensors have quite a lot of use in everyday life. They are used to replace measuring tapes in measuring devices at construction sites. Cars are equipped with ultrasonic parking sensors. Besides measuring distances, they can just register the presence of the object in the measuring range, for example in danger zones of working machines. If ultrasound transmitter and receiver are separated, the flowing speed of the substance between them can be measured, because the sound wave travels slower upstream and vice versa.
HomeLab is equipped with Devantech SRF04/SRF05 ultrasonic distance sensor. SRF04/SRF05 is just a sensor and it does not give direct information about the distance. Besides the power supply pins the sensor has also a triggering pin and a echo pin. When the triggering pin is set high the sensor generates 40 kHz ultrasonic wave which is 8 periods long. At that moment the echo pin becomes high and remains high until the reflected sound is reached back to the sensor. So the echo signal reflects basically the time during which the sound reaches to the object and comes back from the object. By measuring that time and multiplying it by the speed of sound and then divide it by two, is calculated the distance to the object. The following graph represents the relationship of time and the signals of sound transmitter, trigger and echo:
To use the SRF04/SRF05 with the AVR, its trigger pin and echo pin should be connected to some of the AVR pins. For measuring time, it is suitable to use a 16-bit timer, for example timer3. Following is a function which executes all measuring procedures – it generates the signal of the trigger, starts the timer, measures the length of the echo signal and converts it to the distance in centimeters. The function is blocking, meaning the processor is occupied by it until the result of measuring is received or the measuring takes too long time. The faster the echo arrives the faster the result is returned. If the echo does not arrive, the function waits for it for 36 ms and returns to 0. It is important to leave approximately 20 ms break between each measuring, to able the sound generated during the previous measuring to die out and the new measuring will not be affected. It is important to notice that the sound waves don’t disturb each other, when several ultrasonic sensors are used simultaneously
#define ULTRASONIC_SPEED_OF_SOUND 33000 // cm/s // // Instant ultrasonic distance measuring // unsigned short ultrasonic_instant_measure(pin trigger, pin echo) { // Pin setup pin_setup_output(trigger); pin_setup_input_with_pullup(echo); // Set timer 3 to normal mode // with period of F_CPU / 8 timer3_init_normal(TIMER3_PRESCALE_8); // Create trigger pulse pin_set(trigger); // Reset timer timer3_overflow_flag_clear(); timer3_set_value(0); // Wait ~10 us while (timer3_get_value() < 18) {} // End trigger pulse pin_clear(trigger); // Wait for echo start while (!pin_get_value(echo)) { // Timeout ? if (timer3_overflow_flag_is_set()) { return 0; } } // Reset timer again timer3_set_value(0); // Wait for echo end while (pin_get_value(echo)) { // Timeout ? if (timer3_overflow_flag_is_set()) { return 0; } } // Convert time to distance: // distance = timer * (1 / (F_CPU / 8)) * speed / 2 return (unsigned long)timer3_get_value() * ULTRASONIC_SPEED_OF_SOUND / (F_CPU / 4); }
Presented function allows the user to choose the echo pin and the trigger pin, so the sensor can be connected where it is more suitable or where is more space. In addition, the freedom of choosing the pins allows to use the function also elsewhere than only in the HomeLab. Presented function belongs already to the library of the HomeLab so it is not necessary to write it. One thing must be remembered: the function in the library of the HomeLab is stiffly connected to the clock rate of the Controller module of the HomeLab. The clock rate is 14,7456 MHz and while using the function with other clock-rates, it would give incorrect result. To use the function with other clock-rates, it should be written in the program manually. Following code of program demonstrates the use of SRF04/SRF05 ultrasonic sensor with the library of the HomeLab.
// // The example program of the ultrasonic distance sensor of the HomeLab // Measuring the distance is blocking. // #include <stdio.h> #include <homelab/pin.h> #include <homelab/delay.h> #include <homelab/module/sensors.h> #include <homelab/module/lcd_gfx.h> // // Pins of ultrasonic sensor // pin pin_trigger = PIN(G, 1); pin pin_echo = PIN(G, 0); // // Main program // int main(void) { unsigned short distance; char text[16]; // Switching to external sensors pin ex_sensors = PIN(G, 0); pin_setup_output(ex_sensors); pin_set(ex_sensors); // Initialization of LCD lcd_gfx_init(); // Clearing the LCD lcd_gfx_clear(); // Line selection lcd_gfx_goto_char_xy(1,2); // Name of the program lcd_gfx_write_string("Ultra sound"); // Little break sw_delay_ms(100); // Endless loop. while (true) { // Measuring distance = ultrasonic_measure_srf04(pin_trigger, pin_echo); // Was the measuring successful ? if (distance > 0) { // converting the distance to text. sprintf(text, "%d cm ", distance); } // Were there errors during the measuring ? else { // Text of the error. sprintf(text, "Error "); } // Displaying the text on the LCD lcd_gfx_goto_char_xy(3, 3); lcd_gfx_write_string(text); // Little break. sw_delay_ms(500); } }