HC SR 04 in Assembler

Gast #4548103
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
#4548139
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
Gast #4548443
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
Gast #4549547
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
Gast #4549677
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)
Gast #4833821
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
(Firma: Vescomp) #4833838
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.
Angehängte Dateien:
Gast #4839373
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren