Mein erstes fertiges Projekt: Abstandsmessung mit HC-SR04 in Assembler Soweit meine Suchen ergaben, gibt es noch keinen fertigen Assembler-Code für das Ultraschall-Teil im Forum (oder Netz). Jedenfalls bin ich nicht fündig geworden und habe daher ohne Vorlage selbst ein Programm geschrieben. Für Anregungen bin ich absolut offen. Da es mein erstes Assembler-Projekt ist, reicht es für mich zunächst, dass alles funktioniert. Verbesserungen kommen in der Version 2.0 (z.B. Erweiterung der maximalen Messdistanz von 70cm auf 300cm). Ich hoffe die Dokumentation im Sourcecode ist übersichtlich und verständlich. Anmerkung zu Zeile 250 ff: Die Verschiebung der Register ist natürlich unnötig, aber ich wollte das Programm vorerst so belassen, damit es in der ersten Version endlich fertig ist. LG Chris
Ein Kommentar, für welche CPUs das geht und für welche nicht, wäre hilfreich.
Sorry. Ja. Atmega8. Für welche anderen uC es funktioniert, muss ich noc testen - falls das mit der Software ausreichend ist. LG Chris
Hi >Da es mein erstes >Assembler-Projekt ist, reicht es für mich zunächst, dass alles >funktioniert. Nicht ganz. Dein Programmteil 'Berechnung' ist fehlerhaft. Bei einer Differenz timer1-timer0=50 müsste am Ende der Multiplikation (50*16*1715) 1372000 herauskommen. Dein Programm errechnet 1411200.
1 | sub timer1, timer0 ; t1-t0 |
2 | ldi temp1, 255 |
3 | add timer1, temp1 ; +255 |
4 | ldi temp1, 1 |
5 | add timer1, temp1 ; +1 |
Wenn du zu einem 8-Bit-Register 256 addierst ändert sich am Registerinhalt gar nichts. Einen Overflow (Cy-Flag) berücksichtigst du ja nicht. Die Addition ist somit sinnfrei.
1 | Eins: |
2 | subi r16, byte1(1) |
3 | sbci r17, byte2(1) |
4 | sbci r18, byte3(1) |
5 | .... |
Dir ist bewusst, das beim Label 'Eins' die Einerstelle schon in r16 steht? Da reicht ein ' sts D_E, r16. Ist nicht alles. MfG Spess
Wenn man schon alles in Assembler machen muss, kann man es auch selber mahcne...
Danke spess53! Ich arbeite gerade alles durch, um es auf 300cm zu erweitern. und da ist es mir aufgefallen. War ein dummer Fehler; außerdem fehlt das High-Register... Auch die Routine für die Multiplikation habe ich rausgeschmissen und anders gelöst. @hobbymechaniker: Ich verstehe Deinen Kommentar nicht. Meinst Du die fertigen Bausteine, die ich aus dem Tutorial übernommen habe (LCD)?
Version 2.0 - korrigiert und einzatzfähig Hardware: - ATmega 8 (Standardbeschaltung (AVR-Tutorial: Equipment: Selbstbau) - HC-SR04 (Trigger an PORTB, Echo an PORTD, LCD and PORTC) - LCD (16x2, HD44780) Bug: - angezeigter Abstand konstant ca. 5mm zu wenig. Ich habe die Berechnung und Anzeige mit vorberechneten Werten geteste und es ergab den korrekten Abstand. Im Programm ist der Teil, der die Messung durchführt zu einfach für Fehler(?): - steigende Flanke des Echo (HC-SR04) löst INT0 aus (Overflow- Counter wird auf 0 gesetzt, Timer-Stand wird gespeichert) - fallende Flanke löst INT1 aus, der wieder dem Timerstand speichert und die Interrupts deaktiviert (keine weiteren Overflows während der Berechnung) - umgerechnen und ausgeben Änderungen zur Version 1: - Korrektur der Berechnungsfehler - max. Messdistanz 300cm (statt bisher 70cm) - ein paar Vereinfachungen und Verschönderungen im Sourcecode Falls jemand dieses Programm praktisch ausprobiert, wäre es interessant, wie die Ergebnisse mit anderen HC-SR04s aussehen (was die Messfehler angeht). Bitte posten. Ich gebe das Program natürlich vollkommen frei was copyright angeht. Über Rückmeldungen, Verbesserungsvorschläge usw. freue ich mich. Es ist mein ersten Projekt und ich bin sehr froh, dass es funktioniert und (so weit ich es bisher getestet habe) nur einen Bug hat :) LG Christian P.S. Datenblatt des HC-SR04 ist im ersten Beitrag ganz oben.
Hi
>Version 2.0 - korrigiert und einzatzfähig
Wohl etwas voreilig.
1 | Int1_ISR: |
2 | ... |
3 | rjmp main1 ; !!!!!!!!!!!!!!!!!!! |
4 | reti |
Damit bekommst du früher oder später einen Stackoverflow. Am besten du verlagerst die ganze Brechnung und Ausgabe in deinen Mainloop. In der ISR werden nur der Timer eingelesen und ein Flag gesetzt. [/avrasm] .def temp1 = r16 ... mov r16, timer0 [/avrasm] Was nun? Ist r16 nun temp1 oder nicht? Du musst dich schon entscheiden ob du dieses .def-Gedödel benutzt oder nicht. Im ersten Fall haben die Registerbezeichnungen Rxy nichts mehr Programm zu suchen. Oder du verzichtest, wie ich persönlich, ganz darauf. >; Berechnung der Zeit (t = (t1 - t0 + 256 * ovfl) * 16 [µs] ) >; Berechnung des Abstandes ( dist [cm] = time [ms] * 17,15 >; ----> dist [cm] = time [µs] 1715 10^-5 >; ====> dist [cm] = time [µs] 49 35 * 10^-5 >; die Bytes sind von highest zu lowest: distHH distH distL / distLL Wenn man das mal zusammenfasst kommt man auf t = ((256 * ovfl + t1) - t0 ) 16 1715. Also eine 16-Bit- Subtraktion und eine 16x16-Bit-Multiplikation. Warum machst du das nicht?
1 | Berechnung: |
2 | clr r2 ; Null |
3 | |
4 | sub timer1, timer0 ; 16-Bit-Subtraktion |
5 | sbc ovfl, r2 ; |
6 | |
7 | ldi temp1, low(16*1715); 16x16 Bit Multiplikation |
8 | ldi temp2,high(16*1715) |
9 | |
10 | mul timer1,temp1 |
11 | mov distLL,r0 |
12 | mov distL, r1 |
13 | |
14 | mul ovfl, temp2 |
15 | mov distH, r0 |
16 | mov distHH,r1 |
17 | |
18 | mul timer1,temp2 |
19 | add distL, r0 |
20 | adc distH, r1 |
21 | adc distHH,r2 |
22 | |
23 | mul ovfl, temp1 |
24 | add distL, r0 |
25 | adc distH, r1 |
26 | adc distHH,r2 |
27 | .... |
Fertig. Mit etwa einem Drittel deines Codes.
>- ein paar Vereinfachungen und Verschönderungen im Sourcecode
Ich habe eher den Eindruck, das du das Programm verschlimmbesserst hast.
Vereinfachung wäre z.B. die obige Berechnung oder den Spagetticode der
Ausgabe durch eine Schleife
1 | text: .db "Abstand [cm]:",0 |
2 | |
3 | Ausgabe: ldi ZL, Low(text<<1) |
4 | ldi ZH,high(text<<1) |
5 | |
6 | ldi temp1, 0b10000000 ; Ausgabe in erster Zeile: 'Abstand [cm]:' |
7 | rcall lcd_command |
8 | |
9 | Ausgabe10: lpm temp1, Z+ |
10 | tst temp1 |
11 | breq Ausgabe20 |
12 | |
13 | rcall lcd_data |
14 | |
15 | rjmp Ausgabe10 |
16 | |
17 | Ausgabe20: ... |
zu ersetzen. MfG Spess
spess53 schrieb: >>; Berechnung des Abstandes ( dist [cm] = time [ms] * 17,15 Das wird genau bei Zimmertemperatur funktionieren, da die Schallgeschwindigkeit kräftig von der Temperatur abhängt. Pro Grad ändert sie sich um etwa 0.6 m/s
Mike schrieb: > Das wird genau bei Zimmertemperatur funktionieren Ja, daher steht im Datenblatt, dass es für Außeneinsatz sinvoll wäre, eine Temeratur- bzw. Feutchitgkeitskompension zu machen. Das wäre ein nächster Schritt...
Danke Spess!!! Da sieht man den Unterschied zwischen Programmier-Babay (zumidest bei Assembler) und denen, die schon laufen können. Deine Vorschläge finde ich echt elegant! spess53 schrieb: > Damit bekommst du früher oder später einen Stackoverflow. Ups. Gar nicht bedacht... > [/avrasm] > .def temp1 = r16 > ... > mov r16, timer0 > [/avrasm] > > Was nun? Ist r16 nun temp1 oder nicht? Meine Überlegung war, eine allgemeine Routine zu schreiben. Daher der Wechsel zu r16 usw. > t = ((256 * ovfl + t1) - t0 ) 16 1715. Also eine 16-Bit- > Subtraktion und eine 16x16-Bit-Multiplikation. Warum machst du das > nicht? Das gefällt mir! Ich hätte die Ide nie gehabt. Dass ein Übertrag mit r2 funktioniert, war mir neu. > Vereinfachung wäre z.B. die obige Berechnung oder den Spagetticode der > Ausgabe durch eine Schleife Was soll ich sagen... Danke! Dass Du meinen Code durchgehst und Vorschläge machst, hilft mir absolu weiter! Danke! LG Chris
Christian Haerringer schrieb: > Ja, daher steht im Datenblatt, dass es für Außeneinsatz sinvoll wäre, > eine Temeratur- bzw. Feutchitgkeitskompension zu machen. Die Fehler durch fehlende Berücksichtigung der Feuchte sind wesentlich geringer, als der Temperatureffekt.
Hi
>Ups. Gar nicht bedacht...
Hauptsache du machst da nicht wieder ein 'rjmp main' rein. Das macht
zwar keinen Stackfehler, ist aber auch nicht besser.
MfG Spess
:) Nein. Den Vorschlag mit Flag habe ich schon vertanden :) (rjmp main erinnert mich an Nils Bohr bei der Physikprüfung)
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.