Forum: Mikrocontroller und Digitale Elektronik Brauche extrem genauen Counter (Mega8,C)


von Orikson (Gast)


Lesenswert?

Hi,

ich bin am experimentieren, wie ich einen sehr genauen Zähler in C 
schreiben kann.

Ich habe mich bereits an dem 8-Bit Timer versucht:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Timer.2FCounter_des_AVR

Dazu habe ich den CPU Frequenzteiler von 1024 verwendet und dann jeden 
Overflow i++ rechnen lassen. Dann wurde das ganze ausgewertet, wenn i > 
3906 ist, sollte eigentlich eine Sekunde rum sein und eine LED leuchten. 
Allerdings braucht die 2-3 Sekunden bis sie endlich angeht, was 
warscheinlich an der if Schleife liegen wird.

Vorhaben ist folgende: Ich möchte mit einer Schaltung und je einen 
Ultraschallempfänger/-sender einen Abstand von 10 - 100 cm messen 
können. Die Schallgeschwindigkeit in Luft beträgt 34300 cm/s, da der 
Schall zum Boden und wieder zurück muss, sind es bei 10 cm Messenfernung 
20 cm, die der Schall zurücklegen muss, also braucht er dafür: 34300/20 
s?

von johnny.m (Gast)


Lesenswert?

Ich glaub Du hast da was gewaltig verdreht... Für einen cm braucht der 
Schall 1/34300 s, also 29,15µs. Für 20 cm sind das 583 µs.

von Roland P. (pram)


Lesenswert?

Für dein Anliegen dürfte sich der Input Capture Pin eignen.

Dass deine LED erst nach 2-3 Sec angeht liegt wahrscheinlich daran, dass 
du die Fuses noch nicht richtig programmiert hast und der AVR mit dem 
internen 1MHz Osc. läuft.

ACHTUNG: Vor dem Programmieren der Fuses unbedingt den Abschnitt im 
Tutorial lesen.
Immer erst die Fuses auslesen und die entsprechenden Fuses dann ändern.
Bei falsch gesetzten Fuses kanns dir passieren dass du den Proz. nicht 
mehr programmieren kannst.

Gruß
Roland

von Falk B. (falk)


Lesenswert?

@ Orikson

>ich bin am experimentieren, wie ich einen sehr genauen Zähler in C
>schreiben kann.

Das hat mit C wenig zu tun, eher mit der Hardware des uC.

>Dazu habe ich den CPU Frequenzteiler von 1024 verwendet und dann jeden
>Overflow i++ rechnen lassen. Dann wurde das ganze ausgewertet, wenn i >
>3906 ist, sollte eigentlich eine Sekunde rum sein und eine LED leuchten.
>Allerdings braucht die 2-3 Sekunden bis sie endlich angeht, was
>warscheinlich an der if Schleife liegen wird.

Genaue Zähler arbeiten nicht mit If-Schleifen (wobei es If-Schleifen gar 
nicht gibt)

>Vorhaben ist folgende: Ich möchte mit einer Schaltung und je einen
>Ultraschallempfänger/-sender einen Abstand von 10 - 100 cm messen
>können. Die Schallgeschwindigkeit in Luft beträgt 34300 cm/s, da der
>Schall zum Boden und wieder zurück muss, sind es bei 10 cm Messenfernung
>20 cm, die der Schall zurücklegen muss, also braucht er dafür: 34300/20
>s?

Schallgeschwindigkeit: 330 m/s = 330mm/ms = 10mm/ 30,3us

Um sowas genau zu messen musst du die Input Capture Funktion benutzten. 
Genaueres steht dazu in jedem Datenblatt.

MfG
Falk


von Roland P. (pram)


Lesenswert?

ich würde dann die Rechnung auch anders machen.

angenommen dein Quarz läuft mit 4 MHz, so schaffst du 343m bei 4000000 
Takten, also 85,75µm je Takt.
Bei einem Prescaler von 64 wären das 5,488 mm/ Timertick
bzw bei nem Prescale von 1024 87,808 mm/ Timertick
Mit dem ICP kannst dann dem Timerwert zum Zeitpunkt des Impulses 
auslesen, am Besten schaust mal ins Datenblatt wie das geht.

Gruß
Roland

von Roland P. (pram)


Lesenswert?

... Falk war schneller :-)

von Orikson (Gast)


Lesenswert?

Hi und danke erst mal für die vielen Antworten!

Ich hab das Datenblatt mal durchgelesen. Sovie wie ich rauslesen konnte 
ist aber nur, dass die Input Capture Funktion auf Pin PB0 liegt, eine 
Schaltung/Code konnte ich nicht finden. Von daher gehe ich mal aus, dass 
das auslesen der ICF reine Softwaresache ist?!

Und bitte steinigt mich nicht, ich bastle erst ne Woche mit dem Mega8 
rum (LCD und Tasten gehen aber schon ;-P)

von Roland P. (pram)


Lesenswert?

du müsstest erst mal deinen Timer richtig initialisieren (Prescaler, 
Input Capture Interrupt)
dann regelmäßig einen US-Burst aussenden und zeitgleich den Timer 
starten.
(das aussenden kann man evtl über Output Compare=0 machen)
Irgendwann tritt dann der ICF-Interrupt ein und da musst nur den dabei 
abgespeichherten Timerwert auslesen, umrechnen und anzeigen :-)
Achtung, je nach Prescaler läuft der Timer früher oder später über...
ich hoffe du hast im ausführlichen Datenblatt, bei mir Seite 120 und 
nicht in der Summary nachgesehen.


Gruß
Roland

von Orikson (Gast)


Lesenswert?

Guten Morgen,

Das Program gibt es schon, aber das ist für einen AT90S8535 gedacht. 
Normalerweiße sollte sich das doch auf nen Mega8 übertragen lassen, 
oder? Mein LCD hängt wie an einem AVR-Ctrl Board im 4 Bit Modus am 
Mega8, ich habe 3 Taster und 3 LEDs und 2 Stecker, an die ich je ein 
Erweiterungsboard hängen kann.

Nachdem ich jetz aber alle Pins etc. angepasst habe meldet mir AVR 
Studio immernoch 15 Fehler. Folgende Variablen sind nicht deklariert: 
GIMSK, GIFR, .EXT_INT1, TIM1_OVF, UBRR, UCR. Außerdem kennt er 
#asm("sei") nicht. Ich würde mal tippen, dass das in ner Headerdatei 
drin ist, die ich nicht eingebunden habe... Folgende habe ich aber 
eingebunden: stdint.h, avr/interrupt.h, avr/io.h, util/delay.h und 
inttypes.h. Dazu noch eine lcd.h die ich mir aus dem Code aus m Tutorial 
hier gebastelt habe und in anderen Projekten funktioniert...

Werde mal den Code raussuchen und hier posten...

von Orikson (Gast)


Lesenswert?

So, hier gibt es den Originalcode (das Demo Program): 
http://mikrocontroller.cco-ev.de/de/projekte.php#uss

Wie muss ich das verändern, damit ich die Fehler von oben nicht mehr 
habe?

von Orikson (Gast)


Lesenswert?

Keiner ne Ahnunng? Über Google finde ich zu diesen Variablen (?) auch 
nichts ...

von Jan (Gast)


Lesenswert?

>>Nachdem ich jetz aber alle Pins etc. angepasst habe meldet mir AVR
>>Studio immernoch 15 Fehler. Folgende Variablen sind nicht deklariert:
>>GIMSK, GIFR, .EXT_INT1, TIM1_OVF, UBRR, UCR.

Diese Register heissen auf einem mega8 schlichtweg anders: UBRR hat 
jetzt 16 Bit mit den Namen UBRRH und UBRRL. Genauso ist UCR aufgeteilt 
in UCSRA und UCSRB.
Die Namen (und Positionen) der einzelnen Bits in den Registern sind auch 
auf allen avrs unterschiedlich, da gibt es keine gemeinsame Norm. Es 
hilft beim Wechsel des Controllers nur das waelzen des Datenblattes. Im 
Allgemeinen heissen die Register aber zumindest aehnlich - man kann also 
einfach die register summary nehmen und nach einem aehnlich Namen 
suchen, in der Regel findet man das passende.

von Orikson (Gast)


Lesenswert?

Hab mich mal durch die Datenblätter gekämpft und die Namen und Werte 
gekämpft und mal geändert... Leider hab ich immernoch exakt die selben 
Fehler, nur dass jetz die angeblich richtigen Namen anstelle der anderen 
auftauchen...

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.