Hallo Community, wie man hier im Forum lesen kann haben sich schon einige mit dem HC-SR04 Ultraschallsensor befasst. Ich habe diese Idee aufgegriffen und mit drei 7-Segment LED Anzeigen als Anzeige des gemessenen Wertes aufgebaut. Die Messung wird im Bereich von ca. 3-300cm erfasst und im Bereich bis 299cm ausgegeben. Problem ist wenn kein Objekt detektiert wird und ich die PORTS (in dem Fall A-C) auf 0 setze, wird ein Wert (04 und 05 meist im Wechsel) ausgegeben. Die PORTS werden nach Abfrage nach der Entfernung zwar noch auf 0 gesetzt, falls der Wert außerhalb des Bereichs ist, jeodch im delay von (hier im Code 150ms) zeigt er die unrealistischen Werte (04 oder 06) auf den LED-Segmentanzeigen an. Ich bräuchte an der Stelle einen kleinen Denkanstoß, da ich nach einigen Stunden und Nerven es nicht hinbekommen habe, dass diese Werte trotz abgefragter Bedingungen nicht mehr ausgegeben werden. Vlt. hab ich auch einfach einen Denkfehler...ich streite es nicht ab^^ Ich hänge den Code an, es kann jedoch sein, dass die letzte if-anweisung nicht mehr ganz komplett ist durch die viele Testerei.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Edit: ich hatte noch #include <stdint.h> eingebunden. Jedoch besteht der Fehler weiterhin, dass die Fehlmessung des Ultraschallsensors auf den Segmenten als unrealistische Werte ausgegeben werden. Im Prinzip sollen nur Werte zwischen 1 und 300 ausgewertet werden und der Rest ignoriert werden, funktioniert aber nicht. bin um jede Idee dankbar.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Hast du dir mal das Datenblatt genau durchgelesen, was in dem Fall passiert, wenn kein Echo zurückkommt ? Das Modul gibt dann einen "langen" Puls als "Fehler" zurück - die Pulsmessung per Timer-Interrupt darf dabei nicht überlaufen.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
In dem Datenblatt, welches ich vorliegen habe steht dazu leider nichts. Muss ich mal nach einem anderen googlen, welches hast du?
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Markus E. schrieb: > Jedoch besteht der Fehler weiterhin, dass die Fehlmessung des > Ultraschallsensors auf den Segmenten als unrealistische Werte ausgegeben > werden. Bevor du an irgendwelchen Segmentanzeigen rumdoktorst, stellt sich doch erstmal die Frage, welche Werte die Variable counter im Fall von Fehlmessungen annimmt. Und Fließkommarechnungen haben in der ISR soetwas von überhaupt nichts zu suchen. time kannst du unmittelbar vor der Ausgabe auf die Anzeige ausrechnen. Und wozu deklarierst du time als double, was real wahrscheinlich auf deinem Compiler als single realisiert ist, wenn du hinterher damit nur Integerrechnung machst?
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Es kommt immer ein Echo zurück. Der Puls hat bei 38ms ein Timeout.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Ich habe das delay auf 10µs geändert (lt. Datenblatt). Vorher hatte ich dort fälschlicherweise 10ms stehen. wenn ich time als uint_16t deklariere wird gar kein Wert mehr ausgegeben auf den Segmentanzeigen.
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
@Wolfgang: ich habe die Berechnung nun aus der ISR rausgenommen und kurz vor der Ausgabe auf die Segmente eingebaut. Habe den jetzigen Code nochmal angehängt. Ich probiere schon den ganzen Tag daran rum, aber bekomme den Code nun gar nicht mehr zum laufen. Kann mir jemand sagen wo mein Fehler ist?
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Ohne alles geprüft zu haben: Wo ist denn die zweite ISR?
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
>>>void main(); ist überflüssig >>> void main(uint16_t counter) Woher soll der Parameter kommen? Der wird hier vermutlich immer 0 sein.
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
>>> time = counter/(F_CPU/256); // (1) >>> time = time / 2.0 * 34300; // (2) Das kann nicht stimmen. F_CPU/256 ergibt 23437, counter ist kleiner als 65536; in (1) kann maximal 2 herauskommen. Dann wird durch 2 (warum 2.0?) geteilt, ergibt maximal 1. nach (2) ist time (als uint16_t) entweder 0 oder 34300, ((time>1) && (time<299)) also nie wahr.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
1 | TCCR1B &= ~(1 << ICES1); |
2 | TCNT1 = 0; |
3 | }
|
4 | else
|
5 | {
|
6 | counter = ICR1; // Zaehlerstand retten |
So funktioniert Input-Capture nicht, vom Auslösen der ISR bis zum ersten Löschen läuft der Timer doch weiter. Wenn Du die Puls-Länge wissen möchtest musst Du die Differenz zwischen zwei Capture-Werten bilden. Und den Überlauf für den die ISR fehlt kann man dabei auch berücksichtigen.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Ich habe den Code nochmal etwas gecleant wie von Josef empfohlen. Das mit 2.0 war natürlich quatsch. Ich habde die Parameter nochmal angepasst. Die Formel habe ich ehrlich gesagt übernommen aus einem anderen Skript und hatte vorher als Zahlentyp für die Variable "time" double geschrieben, damit hat die Anzeige funktioniert nur jetzt weiß ich nicht wie ich die Formel bzw die ISR umschreiben muss.
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
hier
>>> TIMSK |= (1 << TICIE1) | (1 << OCIE1A);// Input Capture Interrupt
Enable+Output Compare A Match Interrupt Enable
erlaubst du ZWEI Interrupts, hast aber immer noch nur EINE ISR.
Ich habe noch nicht drüber nachgedacht, ob beide nötig sind; aber wenn
du ZWEI erlaubst, dann brauchst du auch ZWEI ISRs.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Stimmt du hast recht. Der Compiler hat zwar nicht gemeckert aber ich habe die Zeile direkt angepasst: TIMSK |= (1 << TICIE1);// Input Capture Interrupt Enable
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
So etwas interessiert doch den Compiler nicht.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Um welchen µC geht es hier eigentlich (oder habe ich 'was übersehen)?
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Und die Anzeige kann so auch nicht funktionieren. Die solltest du zuerst korrigieren und TESTEN, wenn du nicht noch eine andere Möglichkeit der Anzeige hast. Anscheinend hast du 3 Stellen zur Verfügung. Dabei hast du wohl die Einer- und Hunderter-Stelle verwechselt (die Hunderter-Stelle kann nur die Werte 0..2 annehmen). Die Bitmuster für die LEDs brauchst du nur einmal, die doch sind vermutlich überaqll gleich (bei den Hundertern kann ich das nicht erkennen). Sie müssen auch nicht berechnet werden, sondern als konstantes Array angelegt werden, z.B. (nicht getestet):
1 | const uint8_t segment7[10] = {0b00111111, ..., 0b01101111}; // müssen 10 Einträge sein! |
2 | messwert = messwert % 1000; // sicherheitshalber nur die letzten drei Dezimalstellen übrig lassen; (0 .. 999) |
3 | PORTB = segment7[messwert/100]; //100er. LED-Segment links |
4 | // time = messwert % 100; // time hat hier nichts zu suchen!
|
5 | messwert = messwert % 100; // 0 .. 99 |
6 | |
7 | PORTA = segment7[messwert/10]; //10er, LED-Segment mitte |
8 | messwert = messwert % 10; // 0 .. 9 |
9 | |
10 | PORTC = segment7[messwert]; //1er, LED-Segment rechts |
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Hallo Josef, die Hunderterstellen müssen nur 0-2 anzeigen das ist schon korrekt so und mehr PINS für die Anzeigen habe ich eh nicht zur Verfügung. Atmel Studio hat zumindest nicht gemeckert sagen wirs mal so ;) Es handelt sich um einen ATmega16. Die Anzeigen funktionieren mit den Bitmustern und der Funktion segment_ausgabe() genau so wie sie sollen, da der Code ja mit "double" Deklaration ja schonmal funktioniert hat. Siehe Code aus Beitrag #1. Was mich daran störte war vorerst die Tatsache, dass auch die Fehlmessungen auf den Anzeigen ausgegeben wurden. Da ich nun deine Verbesserungen eingebaut bzw. geändert hatte und auch von double auf uint_16 Zahlentypen gewechselt habe funktioniert nun die Ausgabe auf die LED-Anzeigen leider gar nicht mehr. Trotzdem bin ich dankbar für alle Tipps die ich bisjetzt von euch bekommen habe und bin stets gewillt mich über Dinge schlau zu machen und den Code zu optimieren. Sehe mich selbst noch eher als Anfänger in Sachen C-Programmierung. In diesem Sinne danke für die Tipps im Anhang habe ich nochmal den aktuellen Code angehängt, der es leider zu keiner Anzeige verschafft. Vlt. kann den Code nochmal jemand prüfen Ich danke dafür
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Markus E. schrieb: > Da ich nun deine > Verbesserungen eingebaut bzw. geändert hatte und auch von double auf > uint_16 Zahlentypen gewechselt habe funktioniert nun die Ausgabe auf die > LED-Anzeigen leider gar nicht mehr. Was heißt "funktioniert gar nicht mehr"? Bleibt alles dunkel? Du hast immer noch eine "dicke" Rechenoperation in der ISR
1 | time = counter/(F_CPU/256); // = Millisekunden |
Und hast du mal von Hand mitgerechnet? Welche Werte nimmt counter an? Welcher Wert ergibt sicht aus der Rechnung counter / 23437? Was erwartest du und was kommt raus, wenn du in main() daraus die Wegstecke berechnest?
1 | time = time / 2 * 34300; // einfache Wegstrecke. Die Schallgeschwindigkeit in trockener Luft |
time finde ich übrigens keinen besonders treffenden Variablennamen für eine Wegstrecke ;-)
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Hallo Wolfgang, ja genau, die Anzeigen bleiben wohl dunkel. Ich möchte es ja nicht bestreiten, dass die Berechnungen mit der Formel nicht stimmen, aber wundere mich eben, da sie mit "volatile double time" vorher auch funktioniert haben. Ich bin deiner Anmerkung gefolgt und habe die Variable "time" durch "distance" ersetzt. Du hast ja recht ;) counter kann ja wegen uint_16t Zahlenwerte zwischen 0..65535 annehmen oder? Muss mir dazu morgen nochmal die Berechnungen zu Gemüte führen, falls da der Fehler begraben liegt. In diesem Sinne einen schönen Abend noch an alle kleiner Edit: indem ich "uint16_t distance = 123;" festlege, kann ich die Segmentanzeigen testen und ausschließen, dass diese nicht funktionieren ;)
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
aber die Anzeige KANN doch so:
1 | PORTB = led3[messwert/100]; //100er. LED-Segment links |
2 | time = messwert % 100; |
3 | |
4 | PORTA = led2[messwert/10]; //10er, LED-Segment mitte |
5 | time = messwert % 10; |
6 | |
7 | PORTC = led1[messwert]; //1er, LED-Segment rechts |
gar nicht funktionieren! Angenommen messwert ist zu Beginn 123. messwert/100 ist dann 1 messwert/10 ist dann 12 >>> PORTB = led3[1]; Das ist noch OK. Die nächste Zeile: >>> time = messwert % 100; ist überflüssig, weil time in der Funktion segment_ausgabe gar nicht benutzt (ausgewertet) wird. >>> PORTA = led2[12]; led2[12] gibt es aber gar nicht; hier wird über das Array-Ende hinaus gelesen; da kann irgend etwas stehen. >>> PORTC = led1[123]; Gibt es auch nicht. Das kann also nicht der Code sein, der funktioniert hat. Und sorry, was ich oben über das VERTAUSCHEN der Einer- und Hunderter-Stelle geschrieben habe, war falsch; der Rest gilt aber dennoch. Vorschlag: 1. Teste zunächst die Function segment_ausgabe(), indem du in einer Schleife mit z.B. 500ms Verzögerung die Zahlen 0 bis 299 anzeigst. 2. Wenn das geht: a) überlege, welchen Wert counter in der ISR maximal annehmen kann. Führe keine Berechnungen (besonders keine Division) in der ISR durch. Entferne die Deklaration von counter in der ISR, und ersetzte volatile uint16_t time = 0; durch volatile uint16_t counter; Alle Berechnungen kommen erst später; deshalb ist der Name counter hier OK. b) ersetze time = time / 2 * 34300; durch distance = counter / ???, vorher als uint16_t in main deklarieren Überlege, durch was du ??? ersetzen mußt, damit für distance maximal der größte darstellbare Wert (=299) herauskommen kann. Das ist jetzt zwar noch nicht wirklich der Abstand, aber du kannst schon 'mal sehen, ob der Wert größer und kleiner wird, wenn man den Abstand verändert. c) Wenn das geht, machst du dir Gedanken, wie die richtige Formel an dieser Stelle lauten muss.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Markus E. schrieb: > counter kann ja wegen uint_16t Zahlenwerte zwischen 0..65535 annehmen > oder? > Im Prinzip: ja. In deinem Programm wird der Zähler ja immer wieder bei 0 gestartet; kann man erst mal so lassen, es gibt aber eine bessere Lösung. Du musst durch einen entsprechenden Vorteiler dafür sorgen, dass er nicht überläuft (habe jetzt nicht überprüft, ob das alles richtig gemacht ist). Dann hängt der Maximalwert von der Taktfrequenz ab und natürlich vom Mess-Signal.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Josef D. schrieb: > Du musst durch einen entsprechenden Vorteiler dafür sorgen, dass er > nicht überläuft (habe jetzt nicht überprüft, ob das alles richtig > gemacht ist). Das hättest du mal überprüfen sollen. Wenn du im Programm guckst, siehst du, dass der Vorteiler dort beim Start jeder Messung auf 256 gestellt wird. Das ist doch ok. Es müßte nicht vor jeder Messung passieren, kann man erstmal aber so lassen, obwohl das natürlich zu Anfang in die Initialisierung gehört. Bei 6MHz CPU-Takt ergibt sich damit eine Taktfrequenz von 23437.5 Hz Falls sich der Sensor bei ausbleibendem Echo so verhält, wie von Rudolph geschrieben, bekommt der Timer damit maximal genau 890 Takte. Rudolph R. schrieb: > Der Puls hat bei 38ms ein Timeout. Bei einem 16-Bit Timer gäbe es also überhaupt keinen Grund für einen Überlauf. Das sieht IMHO alles soweit gut aus. Überdenken muss man die Integerrechnung und die Reihenfolge der Operationen, wie sie in C statt findet.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Ich habe nun die Funktion segment_ausgabe() angepasst (die Variable ist nun überall distance. Hatte vorher übersehen time nach distance umzuschreiben, so ergab die Restwertberechnung natürlich keinen Sinn da hast du recht Josef). Habe der Funktion testweise wie auf dem angehängten Bild den Wert 123 übergeben und dieser wird auch korrekt (wie auf dem anderen angehängten Bild zu sehen) angezeigt. Das funktioniert also schonmal. @Josef: zu 1) deines Vorschlages funktioniert damit nun zu 2) habe die Division in der ISR in die main verlagert wegen dem Vorteiler: den hatte ich auf 256 gesetzt wobei ein Timertakt von 23437.5 herauskommt -wie Wolfgang ja bereits schrieb-. Ich hatte testweise NUR folgende Berechnung stehen lassen: "distance = counter / 2" also ohne "distance = counter/(F_CPU/256)..." Die Werte die auf den Segmentanzeigen angezeigt werden stimmen allerdings noch nicht ganz (6cm auf der Anzeige = 10cm lt. Maßstab). Ich stehe nun ehrlich gesagt noch etwas auf dem Schlauch wie ich auf die korrekten Werte für die Berechnung komme, denn muss nicht auch die Schallgeschwindigkeitsberechnung eingebaut werden? Ich habe den aktuellen Code nochmal angehängt und danke euch vielmals für euere Hilfe. Ich versuche jedem Tipp nachzugehen und habe bereits schon vieles durch eure Tipps dazugelernt und aufgenommen :)
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Markus E. schrieb: > allerdings noch nicht ganz (6cm auf der Anzeige = 10cm lt. Maßstab). Wenn der Controller mit 8 MHz läuft stimmt es fast. Bist Du sicher daß er mit 6 MHz läuft? Edit: Andersrum. Wenn der Controller mit 6 MHz läuft, kommen 6-7cm raus. Bei 8 MHz würden 9-10cm rauskommen.
:
Bearbeitet durch User
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Markus E. schrieb: > Ich hatte testweise NUR folgende Berechnung stehen lassen: > "distance = counter / 2" also ohne "distance = counter/(F_CPU/256)..." > Die Werte die auf den Segmentanzeigen angezeigt werden stimmen > allerdings noch nicht ganz (6cm auf der Anzeige = 10cm lt. Maßstab). Wie sollen sie auch. Wenn du die Schallgeschwindigkeit ignorierst, muss da Unfug herauskommen - fast schon erstaunlich, wie nahe das zufällig an der Wahrheit ist. Natürlich brauchst du den richtigen Umrechnungsfaktor, um von Counter auf die Zentimeteranzeige zu kommen. Wenn ich jetzt richtig gerechnet habe, ist
1 | distance_cm = counter * 2997UL / 4096 |
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
@Peter M: ja der Controller läuft mit 6Mhz ;) @Wolfgang: könntest du mir den Rechenweg deiner Rechnung noch erklären, denn ich denke es funktioniert damit und würde das noch gerne nachvollziehen können. Zumindest die Entfernungen <1m sind ziemlich genau :) Werde die Schaltung morgen an seinem Aufstellort montieren und mal schauen ob die Entfernungen alle richtig angezeigt werden und dann müsste ich mir ggf. noch Gedanken machen darüber wenn Fehlmessungen ausgegeben werden.
Re: HC-SR04 Ultraschallsensor + 7-Segment Anzeigen Problem mit Ausgabe wenn kein Objekt detektiert w
Markus E. schrieb: > könntest du mir den Rechenweg deiner Rechnung noch erklären Der Faktor 2997 stammt aus der Originalumrechnung, allerdings alle konstanten Werte zusammengefasst und mit 4096 skaliert. Ursprünglich hattest du
1 | time = counter/(F_CPU/256); (1) |
2 | distance_cm = time /2 * 34300 |
Zusammengefasst ergibt das
1 | distance_cm = counter/(F_CPU/256) /2 * 34300 (2) |
also
1 | 256 * 34300 |
2 | distance_cm = counter * ------------- (3) |
3 | F_CPU * 2 |
Nach Zusammenfassung der Konstanten
1 | distance_cm = counter * 0.7317 (4) |
oder
1 | 2997 |
2 | distance_cm = counter * ------ (5) |
3 | 4096 |
Die Erweiterung mit 4096 in (5) sorgt dafür, dass trotz der Ganzzahlrechnung genau genug gerechnet wird. Wichtig ist das "UL" damit der Kompiler eine 32-Bit Rechnung macht. Eine 16-Bit Variable würde überlaufen. Die abschließende Division durch 4096, die der µC durch eine einfache Schiebeoperation umsetzen kann, rückt alles zurecht. Das Berechnen der Skalierungskonstante 2997 wird man besser dem Compiler überlassen, damit man später noch mal eine Chance hat, den Quellcode zu verstehen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.