Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage Timer1 ATMEGA 328P


von Peter H. (hp-soft)


Lesenswert?

Hallo zusammen.
Kurz etwas zu mir.
Bin Rentner und möchte mich etwas in der AVR Programmierung in C 
weiterbilden.
Beruflich hatte ich bisher noch nie etwas mit dem programmieren zu tun. 
Privat hat mich die Elektronik und das Programmieren schon vor über 40 
Jahren gepackt. Damals kamen die TTL's aus der 74 Serie zu 
erschwinglichen Preisen auf den Markt. Im Selbststudium habe ich mich 
dann in die Elektronik und das programmieren eingearbeitet. Vom hgw. 
BASIC , VB3.0, BASCOM über ARDUINO komme ich nun zum C. Ich will endlich 
wissen, was intern wirklich passiert. Fertige Funktionen kann fast jeder 
verwenden, aber was dahinter steckt ist interessanter. Und um es vorweg 
zu nehmen: ASM passt nicht mehr in meinen alten Kopf. Das ist mir nun 
wirklich zu Kryptisch.

Nun zu meiner eigentlichen Frage:

Ich will mit dem Ultraschallsensor HC-SR04 rumspielen. Klar gibt es 
unzählige fertige Programme dafür. In BASCOM und beim ARDUINO 
funktioniert es relativ gut.
Ich will aber selbst etwas machen. Damit verstehe ich es dann auch 
besser.

Ich möchte den Timmer1 als Input Capture nutzen
TCCR1A bleibt auf 0x00
TCCR1B ICES1 auf 0 (für fallende Flanke )
       CS10 bis 12 Prescaller einstellen
TIMSK1 ICIE1 für den Input Capture Interrupt setzen
       TOIE1 für Überlauf setzen

Dann im Programm den Timer mit sei() starten
Wenn am ICP1 PIN eine fallende Flanke erkannt wird =>
Sprung in ISR TIMER1 CAPT.
in der ISR :
-ICR1 in 16 Bit Variable speichern
-Timer1 mit cli() stoppen
ISR ENDE

Auswerten der Daten

Ist meine Logik so für den Programmablauf richtig?

von Flunder (flunder)


Lesenswert?

Ohne jetzt nochmal selber im Datenblatt die Bedeutung der Bits 
nachzuschauen, kann ich schonmal sagen cli und sei beeinflussen nur die 
Freigabe aller Interrupts, der Timer läuft weiter, ohne dass eine 
Interruptroutine abgearbeitet werden müsste. Er läuft weiter nach einem 
Überlauf, er kopiert seinen Stand in das Input Capture Register, falls 
er so eingestellt ist, ohne dass die CPU ihm dabei helfen müsste. Man 
kann sogar bei gesperrten Interrupts den Wert aus dem Input Capture 
Register auslesen. Die CPU unterbricht halt nur nicht die Abarbeitung 
des Hauptprogramms für einen Interrupt. Zähler starten und stoppen geht 
über ein oder mehrere Bits, die sich meist im Control Register für den 
Timer befinden. Bei manchen Controllern stoppt man den Timer, indem man 
seinen Takt im Vorteiler abschaltet.

von S. L. (sldt)


Lesenswert?

> Ist meine Logik so für den Programmablauf richtig?

Das Konzept ist wohl noch nicht ganz vollständig: gefragt ist ja die 
Zeitspanne des 'Echo Pulse Output' zwischen steigender und fallender 
Flanke, nachdem zuvor ein 'Trigger Input to Module' auf das HC-SR04 
gegeben wurde.

von Georg M. (g_m)


Lesenswert?

Peter H. schrieb:
> Dann im Programm den Timer mit sei() starten
1
 sei();     // Enable Global Interrupts

https://github.com/SmithIsMyName/ATMega328p_HC-SR04_DMD/blob/master/main.c

von Peter D. (peda)


Lesenswert?

Peter H. schrieb:
> Ist meine Logik so für den Programmablauf richtig?

Nein, da fehlt noch der Zeitpunkt der steigenden Flanke. Schließlich 
will man ja die Pulsdauer haben und nicht den Timestamp einer Flanke 
seit Programmstart.
Typisch läßt man den Timer durchlaufen und bildet die Differenz aus den 
Timstamps beider Flanken.

von Flunder (flunder)


Lesenswert?

Jetzt nochmal mit Datenblatt :
Falls nicht nur Software von Dir läuft, schauen, dass nicht irgendein 
Öko Bit 3 im PRR gesetzt hat oder einfacher : es unbesehen löschen.

Wenn Du nichts ausgeben willst, ist der Waveform Generation Mode 0 
vermutlich der, den Du brauchst. Also WGM10, WGM11, WGM12 und WGM13 auf 
0 setzen. Du willst keine Ausgangspins vom Timer ändern lassen ? Dann 
setze COM1A1, COM1A0, COM1B1 und COM1B0 auf 0.
Ergibt zusammen den Wert 0 für TCCR1A.

Den Wert für TCCR1B kannst Du Dir ja jetzt selber zusammensuchen. Ein 
paar Bits davon hatte ich ja schon erwähnt. Die anderen musst Du setzen, 
je nachdem, ob Du verhindern magst, dass extrem kurze Pulse ein ICP 
auslösen, welche Flanke ICP auslösen soll und wie schnell der Timer 
zählen soll. Wobei Takt vom T1 Pin beziehen höchstwahrscheinlich nicht 
das ist, was Du willst.

Und schon müsste der Zähler zählen... also die Werte in TCNT1 sollten 
sich ändern.

Ich würde sagen, schieb das mit den Interrupts auf später, lass also 
TIMSK1 auf 0 stehen.

Schreibe zum Schluss der Initialisierung 0x27U ins TIFR1.

Wenn Bit 5 vom TIFR1 gesetzt ist, hat mindestens ein ICP stattgefunden. 
Schreibe dann 0x20U in TIFR1, um das Bit zu löschen (klingt erstmal 
komisch, ist aber so und hat durchaus seinen Grund). Dann kannst Du ICR1 
auslesen, um zu erfahren bei welchem Zählerstand das letzte ICP 
stattgefunden hat.

Wenn Bit 0 vom TIFR1 gesetzt ist, ist der Timer übergelaufen. Dieses Bit 
löscht Du durch schreiben von 0x01U ins TIFR1.

von Peter H. (hp-soft)


Lesenswert?

Flunder schrieb:
> Dann kannst Du ICR1
> auslesen, um zu erfahren bei welchem Zählerstand das letzte ICP
> stattgefunden hat.

Zuerst mal vielen Dank für die vielen Antworten.
Noch eine kurze Frage zu ICR1:
Kann ich ICR1 direkt in eine 16 Bit Variable speichern, oder muss ich 
erst ICR1H und dann ICR1L lesen?

von S. L. (sldt)


Lesenswert?

> Kann ich ...

So etwas übernimmt der C-Compiler, also Ersteres.

von Peter H. (hp-soft)


Lesenswert?

Danke. dann hat man etwas Schreibarbeit gespart

von S. L. (sldt)


Lesenswert?

> dann hat man etwas Schreibarbeit gespart

Zwar wurde ja gleich zu Beginn geklärt, dass solche Überlegungen zu 
"kryptisch" sind, trotzdem sei darauf hingewiesen, dass es sich nicht um 
reine Bequemlichkeit handelt: 'For a 16-bit read, the low byte must be 
read before the high byte'.

von Peter H. (hp-soft)


Lesenswert?

S. L. schrieb:
> 'For a 16-bit read, the low byte must be
> read before the high byte'.

Jetzt bin ich durcheinander.
Kann ich jetzt
uint16_t wert=ICR1;
schreiben
oder das LowByte zuerst und dann erst das HighByte?
oder macht das der Compiler ohne mein zutun

von Georg M. (g_m)


Lesenswert?

Peter H. schrieb:
> Kann ich jetzt
> uint16_t wert=ICR1;
> schreiben

Ja. Der Compiler muss schon alles richtig umsetzen.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Peter H. schrieb:
> oder macht das der Compiler ohne mein zutun

Das macht der Compiler für dich, der kennt diese Eigneart bei den 16-bit 
Registern. Also einfach uint16_t Werte benutzen.

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

> wert=ICR1;

Dies - einfach ausprobieren (der Compiler macht das richtig).

Ihre ursprüngliche Alternative
> erst ICR1H und dann ICR1L lesen?
war aber falsch - nur darauf wollte ich hinweisen.

von Peter H. (hp-soft)


Lesenswert?

S. L. schrieb:
> Ihre ursprüngliche Alternative
>> erst ICR1H und dann ICR1L lesen?
> war aber falsch - nur darauf wollte ich hinweisen.

Stimmt, habe schreiben mit lesen verwechselt. Beim schreiben gilt diese 
Reihenfolge

von Rolf (rolf22)


Lesenswert?

Peter H. schrieb:
> im Programm den Timer mit sei() starte
> in der ISR -Timer1 mit cli() stoppen

Nein, so macht man das nicht.

Mit sei()/cli() kann man den Timer nicht beeinflussen. Damit kann man 
nur bestimmen, ob die CPU irgendwelche (Timer und alle anderen) 
Interrupt-Routinen anspringt oder nicht.

Durch Schreiben in TIMSK1 kann man bestimmen, ob der Timer Interrupts 
auslöst oder nicht, er läuft aber unabhängig von dieser Einstellung so, 
wie du ihn initialisiert hast.

Am besten versuchst du es zunächst mal ganz ohne Interrupts, du kannst 
ja in einer Schleife TIFR1 auslesen, um zu sehen, wann das Capture-Event 
kommt.

von Peter H. (hp-soft)


Lesenswert?

Ich habe mal etwas mit dem HC-SR04 nach euren Angaben rumgespielt. Die 
Idee mit dem PIN Change Interrupt war gut. Da kann man ja ohne Probleme 
mehrere Ultraschall Sensoren einsetzen.
Aber ich bin ja immer noch neugierig.
Mir geistert immer noch der TIMER1 CAPT Interrupt im Kopf rum.

So stelle ich mir das vor:
Ich schicke einen 10us Impuls auf den Trigger des HC.
gleichzeitig stelle ich den Timer1 mit TCNT1=0 zurück.
Wenn ich den Echo PIN mit ICP1 Pin verbinde (mit fallender Flanke) 
entsteht doch am Ende des ECHO Signals ein TIMER1 CAPT Interrupt.
Im Interrupt lese ich ICR1 aus
Das Ergebnis ist die Anzahl der Ticks vom Timer1.
( muß nicht mehr berechnet werden und kann direkt weiterverarbeitet 
werden)

Ist das OK so, oder vielleicht nur eine Spinnerei von mir

( nach dem Motto: Geht nicht, gibt es nicht    oder Versuch macht kluch 
)

von S. L. (sldt)


Lesenswert?

Ja, geht; die Genauigkeit ist etwas eingeschränkt.

Ansonsten: zuerst ICP auf positive Flanke, in der ISR (Start des 
Echo-Signals) ICR lesen und speichern und ICP auf negative Flanke 
umstellen, im anschließenden Interrupt (das Ende des Echo-Signals) 
wieder ICR lesen und von diesem Wert den vorher gespeicherten abziehen.

PS:
Das geht auch (wie mehrfach vorgeschlagen) ohne Interrupt, also nur 
durch Abfrage (und explizite Löschung) von TIFR1.ICF1, aber viel 
einfacher wird es dadurch nicht.

PPS:
Fällt mir jetzt erst auf:
> ... nach euren Angaben rumgespielt. Die Idee mit dem
> PIN Change Interrupt war gut
Finde ich nicht, wo steht das?

: Bearbeitet durch User
von Peter H. (hp-soft)


Lesenswert?

S. L. schrieb:
> Ja, geht; die Genauigkeit ist etwas eingeschränkt.
>
> Ansonsten: zuerst ICP auf positive Flanke, in der ISR (Start des
> Echo-Signals) ICR lesen und speichern und ICP auf negative Flanke
> umstellen, im anschließenden Interrupt (das Ende des Echo-Signals)
> wieder ICR lesen und von diesem Wert den vorher gespeicherten abziehen.

2 Fragen dazu:

1. Wieseo ist die Genauigkeit eingeschränkt?
2. Wenn ich direkt ICP auf fallende Flake einstelle und direkt mit dem 
Start des
   Triggersignals Timer1 mit TCNT1=0 zurücksetze
   z.B. PB1=1;
     TCNT1=0;
     _delay_us(10);
     PB1=0;
   dürfte ich doch nur sehr wenige Systemtakte verlieren. (Nur die Dauer 
für das
   Rücksetzen von TCNT1)

von S. L. (sldt)


Lesenswert?

> Wieseo ist die Genauigkeit eingeschränkt?

Deshalb:

> wenige Systemtakte verlieren

Wieviele das sind, würde mich selbst interessieren, probieren Sie beide 
Methoden aus und berichten Sie.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Peter H. schrieb:
> ein TIMER1 CAPT Interrupt

Denke dran, in dieser ISR den Interrupt selber zu sperren, weil nur das 
erste Echo das ist, was du messen möchtest. Erst für den nächsten 
Messzyklus den CAPT IRQ wieder freigeben.

: Bearbeitet durch User
von S. L. (sldt)


Angehängte Dateien:

Lesenswert?

> dürfte ich doch nur sehr wenige Systemtakte verlieren

Oh nein, das Triggersignal ist keineswegs der Beginn des 'Echo Pulse 
Output', dazwischen liegt der '8 Cycle Sonic Burst' und dessen 
Auswertung, und damit eine Zeitspanne, über die das Datenblatt nichts 
aussagt.

PS:
Zeitdiagramm angehängt

: Bearbeitet durch User
von Peter H. (hp-soft)


Lesenswert?

Matthias S. schrieb:
> Denke dran, in dieser ISR den Interrupt selber zu sperren, weil nur das
> erste Echo das ist, was du messen möchtest. Erst für den nächsten
> Messzyklus den CAPT IRQ wieder freigeben.

Das brauche ich nicht unbedingt, da ich die Messzyklen erst wieder nach 
der kompletten Abarbeitung der Auswertung der Ergebnisse selbst im 
Programm wieder starte.
Die automatisierten Messzyklen in den Programmen im Netz haben mich 
immer gestört. Die haben mir immer in meine Auswertung gepfuscht und die 
Ergebnisse gestört.
Trotzdem schalte ich nach der ISR den ICIE1 wieder aus (falls Störimpule 
auf der Echoleitung auftreten) und kurz vor dem Triggerimpuls wieder 
ein.

Danke für den Tip!

von Peter H. (hp-soft)


Lesenswert?

S. L. schrieb:
> Oh nein, das Triggersignal ist keineswegs der Beginn des 'Echo Pulse
> Output', dazwischen liegt der '8 Cycle Sonic Burst' und dessen
> Auswertung, und damit eine Zeitspanne, über die das Datenblatt nichts
> aussagt.

Oh, vielen Dank für die Hilfe.
Kann ich einige Referenzmessungen durchführen und den Mittelwert des 
Fehlers vom Ergebnis abziehen? Dadurch könnte ich dann die Impulse 
zwischen Timerstart und Start des Echo Signals ermitteln
Oder macht es doch mehr Sinn, den Echo PIN mit Pinchange Interrupt zu 
überwachen.
D.h. Start Timer ( 1. Interrupt) bei steigender Flanke Stop Timer (2. 
Interrupt) bei fallender Flanke

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

Ich kann Ihrem Gedankengang nicht ganz folgen (bin auch zu müde).
  Nur soviel, gerade ausprobiert: bei meinem Exemplar liegt zwischen 
pos. Flanke des Triggersignals und pos. Flanke des Echos eine Zeitspanne 
von rund 2.2 ms, unabhängig von der Objektentfernung.

PS:
also tatsächlich 2,2 Millisekunden

: Bearbeitet durch User
von Georg M. (g_m)


Lesenswert?

Peter H. schrieb:
> ... über ARDUINO komme ich nun zum C. Ich will endlich
> wissen, was intern wirklich passiert.

Übrigens, wenn man auf Arduino verzichtet, kann man dann auf die 
obsoleten AVRs auch verzichten.

von Wastl (hartundweichware)


Lesenswert?

Georg M. schrieb:
> Übrigens, wenn man auf Arduino verzichtet

.... geht der Spass erst richtig los. Wer kann der kann ....

von Aloysius P. (Firma: FBI) (a_pendergast)


Lesenswert?

Wie das geht seht exact beschrieben in der Microchip AppNote "AVR135: 
Using Timer Capture to Measure PWM Duty Cycle". Nichts anderes ist das. 
Ein alter Hut. Neuere Chips der NULL-Serie haben dafür eine HW Funktion 
(Pulse Width detection).


https://www.microchip.com/content/dam/mchp/documents/OTH/ApplicationNotes/ApplicationNotes/Atmel-8014-Using-Timer-Capture-to-Measure-PWM-Duty-Cycle_ApplicationNote_AVR135.pdf

von Sebastian W. (wangnick)


Lesenswert?

S. L. schrieb:
> Oh nein, das Triggersignal ist keineswegs der Beginn des 'Echo Pulse
> Output', dazwischen liegt der '8 Cycle Sonic Burst' und dessen
> Auswertung, und damit eine Zeitspanne, über die das Datenblatt nichts
> aussagt.
>
> PS:
> Zeitdiagramm angehängt

Der Text in diesem Zeitdiagramm ist sehr sehr mißverständlich.

Der HC-SR04 funktioniert so: Man erzeugt einen Trigger-Impuls von ~10us 
Dauer. Dies veranlasst den HC-SR04 seine 8 Ultraschallwellen 
auszustoßen, und danach Echo auf HIGH zu setzen. Nach einer Weile läuft 
das Ultraschallecho beim HC-SR04 ein und nach der Erkennung der 8 Wellen 
setzt der HC-SR04 Echo wieder auf LOW. Die Laufzeit des 
Ultraschallsignals entspricht also der Zeit zwischen Echo LOW->HIGH und 
Echo HIGH->LOW.

Die genaueste Art und Weise diese Laufzeiten mit einem Atmega328P zu 
ermitteln ist über ICP. Interrupts sind dafür oft nicht nötig, wenn man 
die Wartezeit bis zum Abbruchkriterium akzeptieren kann.

Mein Code dazu sieht in etwa so aus:
1
#define DIST_DDR DDRD
2
#define DIST_PORT PORTD
3
#define DIST_TRIGGER (1<<PIND6) // TRIGGER 
4
#define DIST_ECHO (1<<PIND6) // PD6 is used as ICP1. The ECHO signal is connected to PD6 via 1k (TRIGGER is connected directly).
5
6
struct Hcsr04 {
7
  uint32_t sum;
8
  uint8_t num, bad;
9
} hcsr04;
10
11
void timer1_setup () {
12
  TCCR1A = 0;
13
  TCCR1B = (1<<CS11);         // Prescaler 8, 2 ticks per μs at 16MHz.
14
  TCCR1C = 0;
15
}
16
17
void hcsr04_measure () {
18
  DIST_DDR |= DIST_TRIGGER; // Make DIST_TRIGGER OUTPUT
19
  DIST_PORT &= ~DIST_TRIGGER;  // OUTPUT LOW
20
  delayMicroseconds(10);           // Output LOW explicitely.
21
  DIST_PORT |= DIST_TRIGGER;   // OUTPUT HIGH
22
  delayMicroseconds(10);           // Wait long enough for the sensor to realize the trigger pin is high. Sensor specs say to wait 10μs.
23
  DIST_PORT &= ~DIST_TRIGGER;  // OUTPUT LOW
24
  delayMicroseconds(10);            // Output LOW explicitely.
25
  DIST_DDR &= ~DIST_ECHO; // Switch to INPUT
26
  delayMicroseconds(10);            // Give echo some time to go low
27
  TCNT1 = 0;
28
  TCCR1B |= (1<<ICES1);            // Trigger on rising edge of ICP1. 
29
  TIFR1 |= (1<<ICF1) | (1<<TOV1); // Clear flags by writing 1
30
  while ((TIFR1 & ((1<<ICF1)|(1<<TOV1))) == 0) continue; // Wait for rising edge or overflow (after 32ms)
31
  if (TIFR1 & (1<<ICF1)) {
32
    uint16_t stick = ICR1;                  // Retrieve timer value stored at rising edge
33
    TCCR1B &= ~(1<<ICES1);        // Trigger on falling edge of ICP1
34
    TIFR1 |= (1<<ICF1);              // Clear flag by writing 1
35
    while ((TIFR1 & ((1<<ICF1)|(1<<TOV1))) == 0) continue; // Wait for falling edge or overflow (after 32ms)
36
    if (TIFR1 & (1<<ICF1)) {
37
      uint16_t etick = ICR1;                 // Retrieve timer value stored at falling edge
38
      hcsr04.sum += etick - stick;
39
      hcsr04.num++;
40
    } else {
41
      hcsr04.bad++;
42
    }
43
  } else {
44
    hcsr04.bad++;
45
  }
46
}

LG, Sebastian

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

Sebastian W. schrieb:
> Der Text in diesem Zeitdiagramm ist sehr sehr mißverständlich.

Für mich war der Text sogar nahezu unverständlich, dafür schien mir das 
Diagramm selbst eindeutig:

S. L. schrieb:
> gefragt ist ja die
> Zeitspanne des 'Echo Pulse Output' zwischen steigender und fallender
> Flanke

von Peter H. (hp-soft)


Lesenswert?

Nach unzähligen Fehlversuchen habe ich mal meinen Ultraschallsensor an 
das Oszi gehangen. Siehe da, es sendet kein Echo. Also ein 
funktionierenden genommen und siehe da es kommt zumindest mal ein 
Ergebnis raus.
Hier ist meine Version für den Ultraschallsensor. 
Verbesserungsvorschläge nehme ich gerne entgegen. Ich muss sie nur mit 
meinem begrenzten Wissen verstehen können.

void HC_SR04_start ()
{
  TIMSK1 |=(1<<ICIE1);    // Interrupt Starten
  PORTD |=(1<<PORTD0);    // Trigger einschalten
  _delay_us(10);      // Trigger dauer
  PORTD &=~(1<<PORTD0);    // Trigger ausschalten
}
void Timer1_init ()
{
  TCCR1A = 0x00;      // nicht gebraucht
  TCCR1B |=(1<<CS11);    // Prescaller von 8
  TCCR1B |=(1<<ICES1);    // steigende Flanke
  TCCR1C = 0x00;      // nicht gebraucht
  TIMSK1 |=(1<<ICIE1);    // Interrupt Starten
}
ISR (TIMER1_CAPT_vect)
{
  if (start==1)
  {
    TCNT1=0;    // Timer zurücksetzen
    TCCR1B &=~(1<<ICES1);  // umstellen aud fallende Flanke
    start=0;    // für Interrupt
  }
  else
  {
    TIMSK1 &=~(1<<ICIE1);  // Interrupt Stoppen
    Dezimalwert=ICR1;  // Timerstand übergeben
    TCCR1B |= (1<<ICES1);  // umstellen auf steigende Flanke
    start=1;    // für Interrupt
  }
}
In der Main rufe ich nur sporadich die HR... Funktion auf und lasse dann 
die Variable Dezimalwert auf meiner LCD Funktion ausgeben.

von Falk B. (falk)


Lesenswert?

Peter H. schrieb:
> Verbesserungsvorschläge nehme ich gerne entgegen. Ich muss sie nur mit
> meinem begrenzten Wissen verstehen können.

Für den Anfang ganz OK.

> void Timer1_init ()
> {
>   TCCR1A = 0x00;      // nicht gebraucht
>   TCCR1B |=(1<<CS11);    // Prescaller von 8
>   TCCR1B |=(1<<ICES1);    // steigende Flanke
>   TCCR1C = 0x00;      // nicht gebraucht
>   TIMSK1 |=(1<<ICIE1);    // Interrupt Starten
> }

> ISR (TIMER1_CAPT_vect)
> {
>   if (start==1)
>   {
>     TCNT1=0;    // Timer zurücksetzen
>     TCCR1B &=~(1<<ICES1);  // umstellen aud fallende Flanke
>     start=0;    // für Interrupt
>   }

Bei Input Capture muss man den Timer nicht anhalten, man läßt ihn 
einfach laufen. Die Differenz aus STOP-START Wert ist immer korrekt, 
auch beim Überlauf, solange die Differenz kleiner als der halbe, 
maximale Zählerstand ist, hier bei Timer 1 816 Bit) 32768.

>   else
>   {
>     TIMSK1 &=~(1<<ICIE1);  // Interrupt Stoppen
>     Dezimalwert=ICR1;  // Timerstand übergeben
>     TCCR1B |= (1<<ICES1);  // umstellen auf steigende Flanke
>     start=1;    // für Interrupt
>   }
> }

> In der Main rufe ich nur sporadich die HR... Funktion auf und lasse dann
> die Variable Dezimalwert auf meiner LCD Funktion ausgeben.

Hoffentlich gesichert über volatile und mit atomarem Zugriff, siehe 
Interrupt.

Beitrag "Re: Atmega/Arduino - Input Capture funktioniert nicht"

von Sebastian W. (wangnick)


Angehängte Dateien:

Lesenswert?

Peter H. schrieb:
> Auswerten der Daten

Man kann mit den rein analogen Varianten des HC-SR04 übrigens eine 
wesentlich höhere Genauigkeit als 3mm erreichen. Anbei der Verlauf des 
Wasserstandes meines Außenteichs als minütlichem simplem Mittelwert von 
60 Messungen.

LG, Sebastian

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.