HC-SR04 Abstandsmessung mit LED-Anzeige

Hallo Forengemeinde,
ich bin völlig neu hier, und versuche mich gerade an einer ersten Programmierung meines Arduino Uno.
Da ich vom programmieren nicht wirklich viel Ahnung habe, suchte ich mir ein wenig Code zusammen ... aber das funktioniert leider so ganz und gar nicht!
Ich hoffe, ihr könnt mir weiter helfen.

Was ich vor habe:
Mit einem HC-SR04 soll der Abstand zu einem Hindernis gemessen werden.
Liegt ein Ergebnis vor, mit einem Abstand kleiner 33cm, so sollen die jeweiligen LED's für eine Sekunde aufleuchten. Ist der Abstand größer 33cm, so soll nach 50 Millisekunden eine neue Messung getätigt werden.

Die LED's sollen nach diesem Prinzip angesteuert werden:

  • liegt der Abstand zwischen 0cm und 6cm, so sollen die Leds 1 bis 10 leuchten
  • liegt der Abstand zwischen 7cm und 12cm, so sollen die Leds 1 bis 7 leuchten
  • liegt der Abstand zwischen 13cm und 18cm, so sollen die Leds 1 bis 4 leuchten
  • liegt der Abstand zwischen 19cm und 25cm, so sollen die Leds 1 bis 2 leuchten
  • liegt der Abstand über 26cm, so soll keine Led leuchten

Diesen Code habe ich geschrieben:

// HC-SR04 VCC => 5V, GND => GND
int TriggerPin = 12;  // Digital 12 => HC-SR04 Trigger
int EchoPin = 13;     // Digital 13 => HC-SR04 Echo
int led1 = 2;           // LED 1 - 2 => rot unten
int led2 = 3;           // LED 1 - 2 => rot unten
int led3 = 4;           // LED 3 - 4 => blau unten/mitte
int led4 = 5;           // LED 3 - 4 => blau unten/mitte
int led5 = 6;           // LED 5 - 7 => orange mitte
int led6 = 7;           // LED 5 - 7 => orange mitte
int led7 = 8;           // LED 5 - 7 => orange mitte
int led8 = 9;           // LED 8 - 10 => grün oben
int led9 = 10;         // LED 8 - 10 => grün oben
int led10 = 11;       // LED 8 - 10 => grün oben

void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
pinMode(led6, OUTPUT);
pinMode(led7, OUTPUT);
pinMode(led8, OUTPUT);
pinMode(led9, OUTPUT);
pinMode(led10, OUTPUT);
}

void loop()
{
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, cm;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(TriggerPin, OUTPUT);
  digitalWrite(TriggerPin, LOW);
  delayMicroseconds(2);
  digitalWrite(TriggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TriggerPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(EchoPin, INPUT);
  duration = pulseIn(EchoPin, HIGH);

  // convert the time into a distance
  cm = microsecondsToCentimeters(duration);
  
  
  if (cm >= 6)
{
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH);
  digitalWrite(led5, HIGH);
  digitalWrite(led6, HIGH);
  digitalWrite(led7, HIGH);
  digitalWrite(led8, HIGH);
  digitalWrite(led9, HIGH);
  digitalWrite(led10, HIGH);
  delay(1000);
}
else if (cm >= 12)
{
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH);
  digitalWrite(led5, HIGH);
  digitalWrite(led6, HIGH);
  digitalWrite(led7, HIGH);
  digitalWrite(led8, HIGH);
  digitalWrite(led9, LOW);
  digitalWrite(led10, LOW);
  delay(1000);
}
else if (cm >= 18)
{
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH);
  digitalWrite(led5, HIGH);
  digitalWrite(led6, HIGH);
  digitalWrite(led7, LOW);
  digitalWrite(led8, LOW);
  digitalWrite(led9, LOW);
  digitalWrite(led10, LOW);
  delay(1000);
}
else if (cm >= 25)
{
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH);
  digitalWrite(led5, LOW);
  digitalWrite(led6, LOW);
  digitalWrite(led7, LOW);
  digitalWrite(led8, LOW);
  digitalWrite(led9, LOW);
  digitalWrite(led10, LOW);
  delay(1000);
}
else if (cm >= 32)
{
  digitalWrite(led1, HIGH);
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, LOW);
  digitalWrite(led5, LOW);
  digitalWrite(led6, LOW);
  digitalWrite(led7, LOW);
  digitalWrite(led8, LOW);
  digitalWrite(led9, LOW);
  digitalWrite(led10, LOW);
  delay(1000);
}
else (cm >= 33);
  {
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  digitalWrite(led4, LOW);
  digitalWrite(led5, LOW);
  digitalWrite(led6, LOW);
  digitalWrite(led7, LOW);
  digitalWrite(led8, LOW);
  digitalWrite(led9, LOW);
  digitalWrite(led10, LOW);
  }
  delay(50);
}
long microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

Spiele ich diesen Code auf den Arduino, so blinken die LED's dauernd, und nur wenn der Ultraschallsensor einen Abstand von unter 6cm erkennt, werden die LEDs alle ausgeschaltet.

Werte zw. 6 und "x" cm werden gänzlich ignoriert :frowning:

Was mache ich falsch???

Gruß Chris

Erstens: so wie eine deiner LED`s eingeschaltet ist, passiert eine volle Sekunde lang-gar nix mehr.
Du hast da nämlich das böse Delay drin.
In der Sekunde geht wirklich überhaupt nichts!

Ob 6cm überhaupt noch funktionieren, weiss ich grad nicht, fangen die HC-SR04 nich in der Gegend überhaupt erst an?

Dann hast du nen weiteren Killer drin, der verhindert, dass allzu oft gemessen werden kann: pulseIn ohne Timeout!
Da dauert eine Messung bis zu einer Sekunde.

Hallo Chris,

hier mal ein Codeschnipsel, wie du die "von - bis" Fenster programmtechnisch einfach realisieren kannstÖ

if ((0 <= voltage) && (voltage < 3.57)) lcd.write(5);     //     0 to 16,66% running time  
if ((3.57 <= voltage) && (voltage < 3.63)) lcd.write(4);  // 16,66 to 33,33% running time
if ((3.63 <= voltage) && ( voltage < 3.67)) lcd.write(3); // 33,33 to 50,00% running time
if ((3.67 <= voltage) && ( voltage < 3.77)) lcd.write(2); // 50,00 to 66,66% running time
if ((3.77 <= voltage) && ( voltage < 3.91)) lcd.write(1); // 66,66 to 83,33% running time
if ((3.91 <= voltage) && ( voltage < 5.0)) lcd.write(0);  // 83,33 to   100% running time
if ((voltage) <= 3.0) digitalWrite(switchOff, 0);         // switch off by undervoltage

du mußt halt die Werte, Variablen und das, was dann passieren soll anpassen, aber das Prinzip sollte aus diesem Beispiel ersichtlich werden. Ich habe das auch nur aus einer analogen Tastaturauswertung (mehrere Tasten über ein Widerstandsnetzwerk an einem Analoginput) für meine Zwecke angepasst. In meinem Fall eine Batterieanzeige auf einem alphanumerischen LCD Display mit selbst definierten Zeichen für den Ladestand.

Gruß Gerald

nix_mehr_frei:
Hallo Chris,

hier mal ein Codeschnipsel, wie du die "von - bis" Fenster programmtechnisch einfach realisieren kannstÖ

Hy,

Rabenauge:
Ob 6cm überhaupt noch funktionieren, weiss ich grad nicht, fangen die HC-SR04 nich in der Gegend überhaupt erst an?

ja der HC-SR04 kann laut Datenblatt von 2 bis 500cm messen.
Für eine erste Spielerei habe ich mir einen kleinen Sketch geladen gehabt, welches die Meßergebnisse an die serielle Schnittstelle ausgibt. Hier waren recht verlässliche Angaben ab 1,3cm vorhanden.

Hallo Gerald,
danke für deinen Code!

Ich habe aber auch weiter gesucht, und bin so auf eine andere Programmierung gestoßen, welche ich ein wenig angepasst habe.
Mittels diesem Sketch werden nun alle 10 LED's je nach gemessenem Abstand automatisch zum leuchten gebracht ... und das funktioniert recht gut!
Als Messbereich ist der Wert "0cm bis 50cm" definiert, und nun wird "alle 5cm" eine weitere LED zum leuchten gebracht.

Hier mal der Code, wäre nett, wenn da dennoch mal jemand drüber schaut!

// HC-SR04 VCC => 5V, GND => GND

const int cNumberOfLeds = 10; // Anzahl der LED's
const int cLed[] = {2,3,4,5,6,7,8,9,10,11}; // Pins, an welche die LED's angeschlossen sind
const int TriggerPin = 12; // Pin für das Triggersignal
const int EchoPin = 13; // Pin für den Echoempfang
// Grenzwerte setzen für Zeit und Messbereich
const unsigned int cHoldDuration = 1000; // LEDs bleiben "x" Millisekunden an
const unsigned int cDurationMax = 2932; // Umrechnung auf der Schallgeschwindigkeit µs je (cm *58,651)
unsigned int duration_min = cDurationMax - 1;
unsigned long start_time = 0;
byte hold_led = 0;
// Messwerte
const unsigned int cBufferSize = 3; // Für die Glättung der Eingangsmesswerte
unsigned int buffer_[cBufferSize];
byte buffer_ptr_ = 0;
unsigned int duration = 0; // Dauer des Impulses vom Ultraschallsensor
void setup()
{
// initialize serial output
Serial.begin(115200);
Serial.println("");
  pinMode(TriggerPin, OUTPUT); // definiert Triggerpin als Ausgang
  digitalWrite(TriggerPin, LOW);
  delayMicroseconds(2); // kurzes Signal für sauberes Meßsignal
  digitalWrite(TriggerPin, HIGH);
  delayMicroseconds(10); // senden des U-schalsignals von "x" ms
  digitalWrite(TriggerPin, LOW);
  pinMode(EchoPin, INPUT); // definiert Echopin als Eingang
  duration = pulseIn(EchoPin, HIGH); // aktiviert Echopin für den Empfang
for(int i = 0; i < cNumberOfLeds; i++)
{
pinMode(cLed[i],OUTPUT);
}
}
void loop()
{
// Ultaschallsensor einlesen
digitalWrite(TriggerPin, LOW);
duration = pulseIn(EchoPin, HIGH);
digitalWrite(TriggerPin, HIGH);
if ((duration < duration_min) && (duration > 250))
{
duration_min = duration;
}
// Messwert begrenzen
duration = constrain(duration, duration_min, cDurationMax);
// Messwert glätten
buffer_[buffer_ptr_] = duration;
buffer_ptr_++;
buffer_ptr_ %= cBufferSize;
duration = 0;
for (byte i = 0; i < cBufferSize; i++)
{
duration += buffer_[i];
}
duration /= cBufferSize;
// Wieviele LEDs müssen leuchten
unsigned int value = map(duration, cDurationMax, duration_min + 20, 0, cNumberOfLeds);
// Hold berechnen
if (value >= hold_led)
{
hold_led = value;
start_time = millis();
}
if ((start_time + cHoldDuration) < millis())
{
hold_led = 0;
}
// Infos auf die serielle Schnittstelle schreiben
Serial.print("Duration: ");
Serial.print(duration);
Serial.print(" \tDuration Min: ");
Serial.print(duration_min);
Serial.print(" \tDuration Max: ");
Serial.print(cDurationMax);
Serial.print(" \tstart_time: ");
Serial.print(start_time);
Serial.print(" \thold_led: ");
Serial.print(hold_led);
Serial.print("\t LED: ");
Serial.println(value);
// LEDs ansteuern
for (int i = 0; i < cNumberOfLeds; i++)
{
digitalWrite(cLed[i], hold_led > i);
}
// Pause bis zur nächsten Messung, Minimalwert = 50 (Zeit für einen Messdurchlauf)
delay(50);
}




Gruß Chris