Forum: Mikrocontroller und Digitale Elektronik HC SR 04 in Assembler


von dannyboy1994 (Gast)


Lesenswert?

Hall community. Ich habe ein Problem mit der Auswertung eines HC-SR04 
Ultraschallsensors. Ich habe es schon auf mehrere Art und Weisen 
versucht aber es will einfach nicht so wie ich es will.

Der erste Versuch war mit Timer ICP Mode. Da bin ich aber so dermaßen 
auf die schnautze gefallen das ich mir gedacht hab ich versuchs einmal 
auf die einfache und primitive Art und weise.
1
.include "tn2313def.inc"
2
.org 0x000    RJMP Main
3
4
.equ trigger=0
5
.equ echo=1
6
.equ sensorport=portb
7
.equ sensorddr=ddrb
8
.equ sensorpin=pinb
9
.def temp1=r16
10
.def temp2=r17
11
.def cm=r20
12
.equ LED=2
13
.org 0x020
14
  Main:
15
    ldi r16, low(RAMEND)
16
    out SPL, r16
17
18
    sbi sensorddr, LED
19
    sbi sensorddr, trigger    ;;Trigger als Ausgang
20
    rcall triggerimpuls
21
    rcall echowait
22
    rcall auswertung
23
    rcall wait50ms
24
    rjmp Main
25
26
  auswertung:
27
  cpi cm, 20
28
  brge aus
29
  cpi cm, 20
30
  brlo an
31
  ret
32
33
  an:
34
  sbi sensorport, LED
35
  ret
36
  
37
  aus:
38
  cbi sensorport, LED
39
  ret
40
41
  wait50ms:
42
43
    ldi  r18, 65
44
      ldi  r19, 239
45
  L12: dec  r19
46
      brne L12
47
      dec  r18
48
      brne L12
49
    ret
50
51
52
53
54
55
  triggerimpuls:
56
    sbi sensorport, trigger
57
58
    ldi temp1, 3
59
    marker01:
60
    nop
61
    dec temp1
62
    brne marker01
63
64
    cbi sensorport, trigger
65
    ldi cm, 0
66
    ret
67
68
  echowait:
69
    sbis sensorpin, echo
70
    rjmp echowait
71
  messen:
72
    ;117 ticks entsprechen 2 cm entfernung bei 1 mhz
73
74
    ldi  r18, 37  ;;
75
    L1: dec  r18  ;;
76
      brne L1      ;;
77
      nop        ;; Das sins 112
78
    
79
    inc cm
80
    inc cm
81
    sbic sensorpin, echo
82
    rjmp messen
83
    ret

Diese Methode Funktioniert nun aber auch nicht zuferlässig. Hat jemand 
von euch vllt verbesserungsvorschläge oder Tipps wie man das ganze doch 
noch funktionstüchtig bekommt.
#mfg Daniel

von Sultan (Gast)


Lesenswert?

> ... schnautze ...

1
Schnauze

von Michael U. (amiga)


Lesenswert?

Hallo,

Du hast sicher eine Erklärung dafür, warum Du diese Initialisierung
1
    ldi r16, low(RAMEND)
2
    out SPL, r16
3
4
    sbi sensorddr, LED
5
    sbi sensorddr, trigger    ;;Trigger als Ausgang

in Deiner Mess-Schleife immer wieder aufrufst?

Was meinst Du mit "nicht zuverlässig"?

Du weißt, daß BRGE einen signed (also das Signed-Flag testet) und BRLO 
einen unsigned (also das Carry-Flag testet) Vergleich macht?
Damit passiert also nicht unbedingt das, was Du erwartest.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von dannyboy1994 (Gast)


Lesenswert?

1
.include "tn13def.inc"
2
.org 0x000    RJMP Main
3
4
.equ trigger=0
5
.equ echo=1
6
.equ sensorport=portb
7
.equ sensorddr=ddrb
8
.equ sensorpin=pinb
9
.def temp1=r16
10
.def temp2=r17
11
.def cm=r20
12
.equ LED=2
13
.org 0x020
14
  Main:
15
    ldi r16, low(RAMEND)
16
    out SPL, r16
17
18
    sbi sensorddr, 3
19
    sbi sensorddr, LED
20
    sbi sensorddr, trigger    ;;Trigger als Ausgang
21
  loop:
22
    rcall triggerimpuls
23
    rcall echowait
24
    rcall auswertung
25
    rcall wait50ms
26
    rjmp loop
27
28
  auswertung:
29
  cpi cm, 22
30
  brge aus
31
  cpi cm, 20
32
  brlt an
33
  ret
34
35
  an:
36
  cbi sensorport, LED
37
  ret
38
  
39
  aus:
40
  sbi sensorport, LED
41
  ret
42
43
  wait50ms:
44
45
    ldi  r18, 65
46
      ldi  r19, 239
47
  L12: dec  r19
48
      brne L12
49
      dec  r18
50
      brne L12
51
    sbi sensorpin, 3
52
    ret
53
54
55
56
57
58
  triggerimpuls:
59
    sbi sensorport, trigger
60
61
    ldi temp1, 3
62
    marker01:
63
    nop
64
    nop
65
    dec temp1
66
    brne marker01
67
68
    cbi sensorport, trigger
69
    ldi cm, 0
70
    ret
71
72
  echowait:
73
    sbis sensorpin, echo
74
    rjmp echowait
75
  messen:
76
    ;117 ticks entsprechen 2 cm entfernung bei 1 mhz
77
78
    ldi  r18, 37  ;;
79
    L1: dec  r18  ;;
80
      brne L1      ;;
81
      nop        ;; Das sins 112
82
    
83
    inc cm
84
    inc cm
85
    sbic sensorpin, echo
86
    rjmp messen
87
    ret

Ich habe nun das ganze etwas ausgebessert. Desweiteren ist noch eine 
kleine KontrollLED mit implementiert die mir anzeigt wann er in die 50ms 
warteschleife springt. Diese sollte ja dann gleichmäßig blincken was sie 
aber nicht tut sondern eher unregelmäßig aufläuchtet. Das ist mir z.B. 
ein Rätsel weil zwischen 20cm und 30 cm distanz der Zeitliche 
unterschied wohl von der Blinckfrequenz zu vernachläsigen wäre. Mit 
nicht zuverläßig meine ich das die LED welche mir eine distanz unter20cm 
anzeigen soll (gegen VCC geschalten) mehr oder weniger treibt was sie 
will...mal läuchtet sie mal nicht. Vllt hast du dafür einen 
Lösungsansatz. Ich werd morgen mal ein kleines Video hochladen um das 
ganze mal etwas zu demonstrieren. Was mir auch noch fehlt ist eine 
kleine Hysterese. Vergleichbar mit der Enprellung eines Tasters. Den an 
einem gewissen Punkt weis er garnicht mehr was er will.

mfg DNAiel

von Jo T. (Gast)


Lesenswert?

Guten Morgen
Nachdem ich schon die Ultraschallis am Raspi probiert habe, jetzt auch 
am ATtiny45.
Danke für den Code.
Ich kann keine Mängel festellen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

dannyboy1994 schrieb:
> Ich habe nun das ganze etwas ausgebessert. Desweiteren ist noch eine
> kleine KontrollLED mit implementiert die mir anzeigt wann er in die 50ms

 Versuche es mal mit mind. 65ms Abstand zwischen den Messungen.
 Ich glaube, dass 50ms einfach zu schnell ist für kurze Entfernungen.

: Bearbeitet durch User
von dannyboy1994 (Gast)


Lesenswert?

Son hier noch einmal ein veränderter Code
1
.include "tn13def.inc"
2
.org 0x000    RJMP Main
3
4
.equ trigger=0
5
.equ echo=1
6
.equ sensorport=portb
7
.equ sensorddr=ddrb
8
.equ sensorpin=pinb
9
.def temp1=r16
10
.def temp2=r17
11
.def cm=r20
12
.equ LED=2
13
.org 0x020
14
  Main:
15
    ldi r16, low(RAMEND)
16
    out SPL, r16
17
18
    sbi sensorddr, 3
19
    sbi sensorddr, LED
20
    sbi sensorddr, trigger    ;;Trigger als Ausgang
21
  loop:
22
    rcall triggerimpuls
23
    rcall echowait
24
    rcall auswertung
25
    rcall wait50ms
26
    rjmp loop
27
28
  auswertung:
29
  cpi cm, 20
30
  brsh aus
31
  cpi cm, 20
32
  brlo an
33
  ret
34
35
  an:
36
  cbi sensorport, LED
37
  ret
38
  
39
  aus:
40
  sbi sensorport, LED
41
  ret
42
43
  wait50ms:
44
45
    ldi  r18, 255;65
46
      ldi  r19, 255;239
47
  L12: dec  r19
48
      brne L12
49
      dec  r18
50
      brne L12
51
    sbi sensorpin, 3
52
    ret
53
54
55
56
57
58
  triggerimpuls:
59
    sbi sensorport, trigger
60
61
    ldi temp1, 3
62
    marker01:
63
    nop
64
    nop
65
    dec temp1
66
    brne marker01
67
68
    cbi sensorport, trigger
69
    ldi cm, 0
70
    ret
71
72
  echowait:
73
    sbis sensorpin, echo
74
    rjmp echowait
75
  messen:
76
    ;117 ticks entsprechen 2 cm entfernung bei 1 mhz
77
78
    ldi  r18, 37  ;;
79
    L1: dec  r18  ;;
80
      brne L1      ;;
81
      nop        ;; Das sins 112
82
    
83
    inc cm
84
    inc cm
85
    sbic sensorpin, echo
86
    rjmp messen
87
    ret

Nun funktioniert es wie gewünscht. Einzig die Angst das er eventuell 
einmal in der Schleife hängen bleiben könnte bleibt. Gibt es noch 
sicherheitsmechanismen die ich mit einfügen könnte?
An alle die den Code kopieren möchten. Nehmt ihn. Freut mich das er euch 
weiter hilft. Anpassen müsst ihr ihn allerdings selbst. Es läuft auf 1 
Mhz. bei 8 Mhz entspricht ein wert "cm" nicht mehr waren 2 sondern 
wahren 16 cm und die schleife für den triggerimpuls muss 8 mal so lang 
sein.
mfg Daniel

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

dannyboy1994 schrieb:
> An alle die den Code kopieren möchten. Nehmt ihn. Freut mich das er euch
> weiter hilft. Anpassen müsst ihr ihn allerdings selbst. Es läuft auf 1

 Keine Ursache, gern geschehen.

von chris (Gast)


Lesenswert?

Hallo,

um es vllt einfacher zu machen und um deine Software zu entlasten lass 
das ding doch einfach über den INT0/1 oder die PCINTx empfangen. 
Pin(Trigger) auf High setzen, in dem man nur mit den internen Pullups 
arbeitet, Counter starten und übern INTx auf die fallende Flanke warten.
Im Int nur die Zeit(Register) auslesen einmal rechts shiften (/2) und 
fertig.

Auf das shiften kann man verzichten wenn man als Grundlage pro Bit nicht 
29,15µs nimmt sondern 58,31µs/Bit entspricht 1cm (mit Rücksicht auf den 
Hin/Rückweg)

von Tom E. (Gast)


Lesenswert?

dannyboy1994 schrieb:
> Einzig die Angst das er eventuell einmal in der Schleife hängen
> bleiben könnte bleibt.

Timeout oder ganz brutal - Watchdog (falls dein µC soetwas hat)

von posti (Gast)


Lesenswert?

Hi

Jupp, ich habe gelesen, daß der Thread bereits einige Tage nicht mehr 
ganz frisch ist.

Wie stabil sind die gemessenen Werte bei Euch?

Selber habe ich probiert, den Timer bei steigender Flanke zu starten und 
bei fallender Flanke zu stoppen.
Heraus kamen Messungen mit +/- 200 Ticks

Beim anderen Versuch, läuft der Timer durchgehend, wird nur beim 
Triggern auf Null gesetzt und bei wechselnder Flanke am Echo-Pin 
gesichert.
Leider habe ich auch hier eine starke Schwankung in ähnlichem Umfang.

Eine Mittelung brachte mir auch noch Nichts, hier war aber wohl ein 
Registerüberlauf schuld.
(erste Messung übernehmen, danach alte Messung x 14 + neue Messung x 2, 
Das durch 16)
Bei Messwerten bis 6000 sollte hier eigentlich Nichts passieren, die 
Anzeige meinte aber, diese Gedanken nicht teilen zu müssen.

Geschrieben in Assembler auf einem ATTiny45 mit AVR-Studio 4 (das 
Neueste lässt sich in der VM nicht installieren).

Ich habe vor, mit diesen Schall-Entfernungsmessern unter Anderem meinen 
Heizöl-Spiegel 'im Auge' zu behalten - es wäre halt einfach nur nett, 
wenn die Anzeige stabil wäre.

MfG

von posti (Gast)


Lesenswert?

Ich vergaß:
Timer wird als 16bit benutzt, im Timer-Überlauf-Interrupt wird ein 
separates Register hochgezählt.
Angezeigt werden die Messwerte dezimal auf einem 7-Seg-Display (MAX7219, 
8 Stellen).

MfG

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

posti schrieb:
> Wie stabil sind die gemessenen Werte bei Euch?

 +/- 1us.
 Allerdings:

 60ms zwischen Messungen.
 Triggerpuls = 25us.
 Pulsende <=> Echobegin = 458us bis 460us.

 Und es funzt ohne Probleme, Fehler im mm-Bereich.

 Hier ein Screenshot, damit du die Zeit vom Pulsende bis Echobegin
 abziehen kannst.

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Hier ein Screenshot, damit du die Zeit vom Pulsende bis Echobegin
>  abziehen kannst.

Kann man auch mittels PinChange-Interrupt lösen, dann muss man keine 
Zeiten abziehen ;)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

M. K. schrieb:
> Kann man auch mittels PinChange-Interrupt lösen, dann muss man keine
> Zeiten abziehen ;)

 Ich mache es so, aber der Fragesteller nicht:

posti schrieb:
> Beim anderen Versuch, läuft der Timer durchgehend, wird nur beim
> Triggern auf Null gesetzt und bei wechselnder Flanke am Echo-Pin
> gesichert.

von posti (Gast)


Lesenswert?

Hi

Danke für die Antworten

Eine Auflösung zumindest bis in die mm hatte ich schwer erhoffe.
Mit dem PCINT hatte ich 'Es' ja auch probiert, dort mit starten/stoppen 
des Timer, wo meine Werte ähnlich zittern waren.

Die aktuellen Timer-Werte werden/wurden bei jedem PCINT je nach 
Pin-Zustand gesichert als Anfang und Ende.
Der Timer bis zum Anfang schwankte um 4 Ticks, was ich mir zwar nicht 
erklären kann (der 40kHz-Burst wird ja wohl identisch ablaufen), aber 
mit leben kann.

Womit sicher gestellt ist, daß der Fehler wieder vorm Monitor sitzt.

Akut muß Das Problem aber noch warten, wollte ein Erfolg und frage einen 
DHT22 ab (kürzeste Verweilzeit 30µs) - noch wollen mich die Steinchen 
aber nicht ganz ernst nehmen :P
(zumindest klappt 'no Slave' wenn kein Sensor gefunden wird - werte ich 
Mal als Teilerfolg :/ )

MfG

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
Noch kein Account? Hier anmelden.