Projekt 1: Schallgeschwindigkeit
Mit dem bekannten Ultraschallmodul HC-SR04 kann man etwa die Distanz von Objekten bestimmen. Hierfür wandelt das Modul die gemessene Laufzeit t mittels “bekannter” Schallgeschwindigkeit c in Luft (rund 340 m/s) in eine Distanz d = c · t/2 um.
Man kann sich aber auch umgekehrt für einen bestimmten Abstand d nur die Laufzeit t anzeigen lassen und daraus mittels c = d / (t/2) die jeweilige Schallgeschwindigkeit berechnen.
Für dieses Projekt benötigt man wie so oft nur einen Arduino, ein 16 x 2 I2C display und eben den HC-SR04 Sensor. Dies kostet aus Fernost zusammen nur um die 10 Euro.
Arduino-Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
// Programm zur Bestimmung der Schallgeschwindigkeit // ================================================= // Gemessen wird die Laufzeit des Ultraschalls vom Sender zum Objekt und wieder zurück zum Empfänger // ------------------------------------------------------------------------------------------------- #include <LiquidCrystal_I2C.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display. ACHTUNG: Adresse kann auch 0x3F sein !!! // Anschlüsse: // GND - GND // VCC - 5V // SDA - ANALOG Pin 4 // SCL - ANALOG pin 5 int trigPin = 3; // set pin 3 as trig pin int echoPin = 4; // set pin 2 as echo pin int time; // ========================= // ======== SEETUP ========= // ========================= void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); // set trig pin as output, we send pulse through this pinMode(echoPin,INPUT); // set echo pin as input, we detect echo through this pin lcd.init(); // initialize the lcd lcd.backlight(); lcd.setCursor(1,0); lcd.print("Bestimmung von"); lcd.setCursor(4,1); lcd.print("v_Schall"); delay(3000); lcd.setCursor(0,0); lcd.print("t = "); lcd.setCursor(4,1); lcd.print(" "); } // ================================ // ======== HAUPTSCHLEIFE ========= // ================================ void loop() { //sending 10 microsecond width pulses, frequency ~ 40KHz digitalWrite(trigPin, LOW); delayMicroseconds(2000); digitalWrite(trigPin,HIGH); // trig pin delayMicroseconds(10); // pulse width 10 microseconds digitalWrite(trigPin, LOW); // trig pin off time = pulseIn(echoPin, HIGH); // pulseIn(), function return time in microseconds //print time on the serial monitor Serial.print(" Time taken for the pulse to travel: "); Serial.print(time); Serial.println(" microseconds"); lcd.setCursor(4,0); lcd.print(" "); lcd.setCursor(4,0); lcd.print(time/2); lcd.print(" us"); delay(400); } |
Projekt 2: Ultraschallanemometer
Mit einem Anemometer bestimmt man die Windgeschwindigkeit. Üblicherweise kommt hier ein Schaufelrad zum Einsatz, welches sich bei einer bestimmten Windgeschwindigkeit mit einer bestimmten Winkelgeschwindigkeit dreht. Man kann ein Anemometer aber auch mit dem Ultraschallmodul HC-SR04 umsetzen. Konkret benötigt man 4 Stück davon. Man muss zuerst von allen Modulen z.B. den Empfänger ablöten. Danach bastelt man aus Holz ein Kreuz. An den 4 Enden des Kreuzes kommt nun je ein Sender. Den jeweiligen Empfänger postiert man genau gegenüber.
Wie kann man nun daraus die Windgeschwindigkeit v berechnen. Nun man bestimmt hintereinander die Laufzeit für alle 4 Strecken (je zwei davon unterscheiden sich nur bzgl. ihrer Richtung). Die Schallgeschwindigkeit c überlagert sich mit der Windgeschwindigkeit v. Es gilt dabei etwa für die x-Richtung:
Geschwindigkeit 1: vx,ges 1 = vx + cx
Geschwindigkeit 2: vx,ges 2 = –vx + cx
Ermittels werden jeweils die beiden Laufzeiten t1 und t2.
Diese hängen mit den Geschwindigkeiten vx,ges wiefolgt zusammen:
vx,ges 1 = d / t1
vx,ges 2 = d / t2
Dies liefert ein Gleichungssystem (2 Glg. mit 2 Unbekannten). Eliminiert man daraus cx, erhält man für die Windgeschwindigkeit vx in x-Richtung:
vx = (d/2) · [(1/t1) – (1/t2)]
Analog dazu lässt sich die Windgeschwindigkeit in y-Richtung bestimmen. Mittels Pythagoras erhält man schlussendlich die Windgeschwindigkeit
v = √(vx² + vy²).
Zusätzlich kennt man durch die Einzelkomponenten vx bzw. vy die Richtung des Winds.
Arduino-Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
// Programm zur Bestimmung der Schallgeschwindigkeit // ================================================= // Gemessen wird die Laufzeit des Ultraschalls vom Sender zum Objekt und wieder zurück zum Empfänger // ------------------------------------------------------------------------------------------------- #include <LiquidCrystal_I2C.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display. ACHTUNG: Adresse kann auch 0x3F sein !!! // Anschlüsse: // GND - GND // VCC - 5V // SDA - ANALOG Pin 4 // SCL - ANALOG pin 5 int VoutPin_x_f = 2; // Vout pin for sensor x_forward int trigPin_x_f = 3; // set pin 3 as trig pin for sensor x_forward int echoPin_x_f = 4; // set pin 4 as echo pin for sensor x_forward int VoutPin_x_b = 5; // Vout pin for sensor x_back int trigPin_x_b = 6; // set pin 6 as trig pin for sensor x_back int echoPin_x_b = 7; // set pin 7 as echo pin for sensor x_back int VoutPin_y_f = 8; // Vout pin for sensor y_forward int trigPin_y_f = 9; // set pin 9 as trig pin for sensor y_forward int echoPin_y_f = 10; // set pin 10 as echo pin for sensor y_forward int VoutPin_y_b = 11; // Vout pin for sensor y_back int trigPin_y_b = 12; // set pin 12 as trig pin for sensor y_back int echoPin_y_b = 13; // set pin 13 as echo pin for sensor y_back float time_x_f, time_x_b, time_y_f, time_y_b; // measured time forward and back in x- and y-direction float time_x_offset_b, time_y_offset_f; // offset-values for x- and y-direction because of different sensor-positions float v_x, v_y, v_total; // velocities in x-, y-direction float distance_x, distance_y; // distance between the receiver and transducer in x- and y-direction // ========================= // ======== SEETUP ========= // ========================= void setup() { Serial.begin(9600); pinMode(VoutPin_x_f, OUTPUT); // set Vout pin as output pinMode(trigPin_x_f, OUTPUT); // set trig pin as output, we send pulse through this pinMode(echoPin_x_f,INPUT); // set echo pin as input, we detect echo through this pin pinMode(VoutPin_x_b, OUTPUT); // set Vout pin as output pinMode(trigPin_x_b, OUTPUT); // set trig pin as output, we send pulse through this pinMode(echoPin_x_b,INPUT); // set echo pin as input, we detect echo through this pin pinMode(VoutPin_y_f, OUTPUT); // set Vout pin as output pinMode(trigPin_y_f, OUTPUT); // set trig pin as output, we send pulse through this pinMode(echoPin_y_f,INPUT); // set echo pin as input, we detect echo through this pin pinMode(VoutPin_y_b, OUTPUT); // set Vout pin as output pinMode(trigPin_y_b, OUTPUT); // set trig pin as output, we send pulse through this pinMode(echoPin_y_b,INPUT); // set echo pin as input, we detect echo through this pin lcd.init(); lcd.backlight(); lcd.setCursor(1,0); lcd.print("Ultraschall"); lcd.setCursor(4,1); lcd.print("Anemometer"); delay(3000); lcd.setCursor(1,0); lcd.print(" "); lcd.setCursor(4,1); lcd.print(" "); lcd.setCursor(0,0); lcd.print("x"); lcd.setCursor(8,0); lcd.print("y"); lcd.setCursor(0,1); lcd.print("v:"); distance_x = 0.47; distance_y = 0.47; time_x_offset_b = 1325.50 - 1307.77; // offsetvalues calculated with the average of 10000 values in both x-directions time_y_offset_f = 1324.54 - 1321.11; // offsetvalues calculated with the average of 10000 values in both y-directions } // ================================ // ======== HAUPTSCHLEIFE ========= // ================================ void loop() { // measuring the velocity forward in x-direction // ============================================= time_x_f = 0.0; digitalWrite(VoutPin_x_f, HIGH); delay(220); for(int i = 0; i < 100; i++) { digitalWrite(trigPin_x_f, LOW); delayMicroseconds(2000); digitalWrite(trigPin_x_f,HIGH); delayMicroseconds(10); digitalWrite(trigPin_x_f, LOW); time_x_f = time_x_f + 1.0 * pulseIn(echoPin_x_f, HIGH); // pulseIn(), function return time in microseconds } digitalWrite(VoutPin_x_f, LOW); time_x_f = time_x_f / 100.0; Serial.print("t_x_f = "); Serial.println(time_x_f,2); // measuring the velocity back in x-direction // ========================================== time_x_b = 0.0; digitalWrite(VoutPin_x_b, HIGH); delay(220); for(int i = 0; i < 100; i++) { digitalWrite(trigPin_x_b, LOW); delayMicroseconds(2000); digitalWrite(trigPin_x_b,HIGH); delayMicroseconds(10); digitalWrite(trigPin_x_b, LOW); time_x_b = time_x_b + 1.0 * pulseIn(echoPin_x_b, HIGH); // pulseIn(), function return time in microseconds } digitalWrite(VoutPin_x_b, LOW); time_x_b = (time_x_b / 100.0) + time_x_offset_b; Serial.print("t_x_b = "); Serial.println(time_x_b,2); // measuring the velocity forward in y-direction // ============================================= time_y_f = 0.0; digitalWrite(VoutPin_y_f, HIGH); delay(220); for(int i = 0; i < 100; i++) { digitalWrite(trigPin_y_f, LOW); delayMicroseconds(2000); digitalWrite(trigPin_y_f,HIGH); delayMicroseconds(10); digitalWrite(trigPin_y_f, LOW); time_y_f = time_y_f + 1.0 * pulseIn(echoPin_y_f, HIGH); // pulseIn(), function return time in microseconds } digitalWrite(VoutPin_y_f, LOW); time_y_f = (time_y_f / 100.0) + time_y_offset_f; Serial.print("t_y_f = "); Serial.println(time_y_f,2); // measuring the velocity back in y-direction // ========================================== time_y_b = 0.0; digitalWrite(VoutPin_y_b, HIGH); delay(220); for(int i = 0; i < 100; i++) { digitalWrite(trigPin_y_b, LOW); delayMicroseconds(2000); digitalWrite(trigPin_y_b,HIGH); delayMicroseconds(10); digitalWrite(trigPin_y_b, LOW); time_y_b = time_y_b + 1.0 * pulseIn(echoPin_y_b, HIGH); // pulseIn(), function return time in microseconds } digitalWrite(VoutPin_y_b, LOW); time_y_b = time_y_b / 100.0; Serial.print("t_y_b = "); Serial.println(time_y_b,2); delay(5); // =================================================== // Calculation of the velocities in x- and y-direction // =================================================== v_x = distance_x * 0.5 * 1000000.0 * ((1.0/time_x_f) - (1.0/time_x_b)); v_y = distance_y * 0.5 * 1000000.0 * ((1.0/time_y_f) - (1.0/time_y_b)); v_total = sqrt(v_x * v_x + v_y * v_y); Serial.print("v_x = "); Serial.println(v_x); Serial.print("v_y = "); Serial.println(v_y); Serial.println(" "); lcd.setCursor(2,0); lcd.print(" "); lcd.setCursor(10,0); lcd.print(" "); lcd.setCursor(3,1); lcd.print(" "); lcd.setCursor(2,0); lcd.print(v_x,1); lcd.setCursor(10,0); lcd.print(v_y,1); lcd.setCursor(3,1); lcd.print(v_total,2); delay(50); } |
Projekt 3: 3D-Ultraschallscanner
Postiert man das Ultraschallmodul HC-SR04 auf einer schwenkbaren Servo-Montierung, so kann man die Entfernung d in einer bestimmten Raumrichtung (Winkel phi und teta) bestimmen. Dies liefert für viele verschiedene Richtungen einen kompletten Raumscan, welcher sich dann 2-dimensional etwa mit der Software gnuplot darstellen lässt.
Arduino-Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
// ========================================================================= // ====== Programm zur Erstellung eines 3D-Scans mittels Ultraschall ======= // ========================================================================= #include <Servo.h> // Inkludiert die Servodateien #include <i2cmaster.h> // Inkludiert die i2c-Bus-Dateien #define TRIGPIN 3 // Pin to send trigger pulse #define ECHOPIN 4 // Pin to receive echo pulse Servo servo_horiz; // Definiert den horizontalen servo Servo servo_verti; // Definiert den vertikalen servo int taste; // Tastaturpin für Start des Scans int winkel_horiz; // horizontaler Winkel int winkel_verti; // vertikaler Winkel int horiz_start = 120; // horizontaler Startwinkel int verti_start = 70; // vertikaler Startwinkel int schritte = 30; // horizontale bzw. vertikale Schritte int schrittweite = 3; // Schrittweite der Servos int distance = 0; // Distanz in cm // ************************************ // ************** SETUP *************** // ************************************ void setup() { Serial.begin(9600); servo_horiz.attach(9); // Set horizontalen servo to digital pin 9 servo_verti.attach(10); // Set vertikalen servo to digital pin 10 pinMode(13, OUTPUT); pinMode(ECHOPIN, INPUT); pinMode(TRIGPIN, OUTPUT); } // ******************************************** // ************** HAUPTSCHLEIFE *************** // ******************************************** void loop() { taste = analogRead(A0); // Abfrage, ob die Taste gedrückt wird und der Scan gestartet werden kann servo_horiz.write(horiz_start); servo_verti.write(verti_start); if (taste > 500) { // ********** Messung gestartet ************ digitalWrite(13, HIGH); // set the LED on delay(1000); // wait for a second digitalWrite(13, LOW); // set the LED off for (int i = 0; i <= schritte; i++) { servo_horiz.write(horiz_start); winkel_verti = verti_start + i * schrittweite; servo_verti.write(winkel_verti); delay(250); for (int j = 0; j <= schritte; j++) { winkel_horiz = horiz_start - j * schrittweite; servo_horiz.write(winkel_horiz); delay(500); digitalWrite(TRIGPIN, LOW); // Set the trigger pin to low for 2 µS delayMicroseconds(2); digitalWrite(TRIGPIN, HIGH); // Send a 10 µS high to trigger ranging delayMicroseconds(10); digitalWrite(TRIGPIN, LOW); // Send pin low again distance = pulseIn(ECHOPIN, HIGH); // Read in times pulse distance= distance / 58; // Umrechnung der doppelten Laufzeit in µsek auf die Distanz bei einer Geschwindigkeit von 33 000 cm/sek Serial.print(schritte * schrittweite - j * schrittweite); Serial.print(" "); Serial.print(winkel_verti - 70); Serial.print(" "); Serial.println(distance); } } // ********** Messung beendet ************ digitalWrite(13, HIGH); // set the LED on delay(1000); // wait for a second digitalWrite(13, LOW); // set the LED off servo_horiz.write(horiz_start); servo_verti.write(verti_start); } } |