Frequenz mittels ICP bestimmen und über UART ausgeben.wo steckt der Fehler?

Gast #804606
Lesenswert?

Hallo Leute,

ich habe mir mittels Codesammlung und eigenen Überlegungen ein Programm 
zusammengeschreiben, was am ICP (PD6 vom Atmega32) eine Zeitspanne 
messen soll und diese dann in eine Frequenz umrechnen soll. Die Frequenz 
wird dann in ein char Array umgewandelt und mittels UART zum PC 
gesendet. Die Kommunikation zwischen AVR und PC klappte bis jetzt 
eigentlich immer und ich habe auch nichts verändert. Leider sendet mein 
Programm immer nur komische Zeichen und keine Zahl:( Könnte mal jemand 
meinen Code angucken? Vieleicht seht ihr ja auf Anhieb einen Fehler?
Angehängte Dateien:
Gast #804727
Lesenswert?

Hi,

> ..... Die Kommunikation zwischen AVR und PC klappte bis jetzt
> eigentlich immer und ich habe auch nichts verändert.
"Eigentlich" klingt nicht so gut...
Wenn Du nichts verändert hast, ist was kaputt oder hat sich spontan (?) 
verändert!

> Leider sendet mein
> Programm immer nur komische Zeichen und keine Zahl:
Reduziert sieht Dein Programm so aus:

int main()
{
   uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
   uart_puts("test");
}

Also sollte es auch keine Zahlen senden. Wenn mit der Hardware + 
Initialisierung beidseits alles stimmt, sollte es "test" senden, sonst 
nichts!

Die Overflows zu zählen, ist eine sehr grobe Methode, die allerdings für 
Deine Frequenzen durchaus adäquat sein kann.

Gruß

Fred
Gast #804805
Lesenswert?

Also, habe den fehler gefunden, hatte irgendwas mit den header files 
verpeilt. Nun funktioniert es und ich bekomme mittels uart wunderbar die 
werte ausgegeben. leider bekomme ich alle 5-10 Werte einen Wert, der 
nicht stimmen kann, es ist in etwas das doppelte der Werte von 
davor...wie kann so etwas passieren, oder wie kann ich es vermeiden?
Gast #805402
Lesenswert?

In seltenen Fällen kann ein weiterer Timer-Overflow passieren zwischen 
dem 2 ten ICP und dem Ausgeben im Hauptprogramm.

Ebenfalls eher selten kann der Überlauf und ICP praktisch gleichzeitig 
auftreten. Dann wird erst der ISR mit höherer Priorität abgearbeite, 
obwohl der andere eventuell ein paar Zyklen vorher darn sein sollte. Das 
kann passieren, weil einige Befehle mehr als einen Zyklus brauchen. Für 
den Stopp-Fall wird dieser Fehler durch den oberen gerade wieder 
berichtigt, aber beim Start kann es da zu einem extra Overflow kommen, 
der eigentlich vor dem Start war.

Die oben beschrieben Fälle sind wirklich selten (ca. 1:10000) und 
sollten unabhängig von der Frequenz sein. Die Zeit kann dadurch gerade 
um jeweils einen Overflow zu lang sein.

Wenn der Fehler bei sehr niedrigen Frequenzen auftritt, wird das aber 
eher ein anders Problem sein.
Gast #805429
Lesenswert?

hmmm, hat da jemand vieleicht noch ne Idee, warum gerade bei den 
niedrigen Frequenzen dieser Fehler auftritt, dass all 10 bis 20 
Messungen ein Wert dabei ist, der genau doppelt so hoch is wie die 
anderen?
Gast #805538
Lesenswert?

Bezieht sich das genau doppelt so hoch auf de Frequenz oder die Perioden 
Zeit ?
Das sollte dann eher ein Problem mit der Hardware sein:
Entweder reicht der Pegel nicht ganz aus, und nur Überschwinger triggern 
meistens den ICP oder es gibt bei der anderen Flanke noch ein paar 
Überschwinger die dann auch bei der falschen Flanke triggern.
Gast #805653
Lesenswert?

hmm, naja an hardware gibts bei mir eigentlich nich viel;) ich habe 
einen Tachoausgang eines Lüfters und dieser hängt über einen Pull-up 
Widerstand (10kOhm) an Vcc...kann man das noch anders lösen?
Gast #805820
Lesenswert?

Man könnte versuchen im Controller den Noise Cnacler zu aktivieren. Dann 
werden ganz kurze Pulse Ignoriert. Da es für einen Lufter wohl nicht auf 
5 Stellen ankommt, könnte man auch den Przessortakt etwas runter setzen, 
der Noise Cancler wird dann effectiver. Eventuell könnte man auch in der 
ICP routine noch mal controllieren, ob wirklich der erwartete Pegel am 
ICP Pin anliegt und ggf. das Signal Ignorieren.

Wenn das Signal zu schwach ist, könnte man auch den analogen Komperator 
als Eingang nutzen.

Es ist immer noch nicht klar, ob die Frequenz gelegentlich zu hoch oder 
zu niedrig angezeigt wird ?
Gast #806604
Lesenswert?

Wenn die Frequenz doppelt so hoch ist, dann wird eine extra Flanke nach 
der halben Zeit erkannt. Abhilfe kömmte der noise Cancler bringen, oder 
auch ein kleiner Kondensator am Eingang.
Noise Cancler wird im TCCR1B Register eingeschaltet. Außer für sehr 
kurze Pulse (< 4 Zyklen) gibt der fast keinen Nachteile.

Auch die Software Lösung, den Zustand nach dem ICP abzufragen sollte 
helfen.
Gast #807924
Lesenswert?

Hab das Problem jetzt gelöst, indem ich den aktuellen Wert immer mit dem 
vorherigen vergleiche und so keine groben Ausreißer zulasse. Nun habe 
ich aber noch eine Frage. Wenn keine Flanken mehr am ICP ankommen, 
wartet das Programm ja solange bis eine Flanke kommt. Wie kann ich es 
erreichen, dass nach einer gewissen Zeit, wo keine Flanke kommt ein 
bestimmtes Ereignis auslösen kann?
#808180
Lesenswert?

Cha_Ko wrote:
> Hmm ok, das versteh ich schonmal, nur weiß ich nich ganz genau wie ich
> es im Code umsetzen soll.

Dann hast du es auch nicht verstanden.

> kannst du mir da nochmal nen Tip geben?

Was für einen Tip brauchst du noch?

> Die Überläufe des Timers zählen,

Das machst du ja schon. Genau das macht die Overflow ISR
indem sie die NrOverflows Variable hochzählt

> und wenn diese Zahl groß genug ist,

D.h. du legst eine Obergrenze fest.

> lässt du irgendwas passieren.

In der Hauptschleife in main() vergleichst du NrOverflows mit
deiner selbstgewählten Obergrenze und wenn beide gleich sind,
hast du dein Ereignis
1
#define MEINE_GRENZE 100
2

3

4
  ...
5

6
sei();
7
  while(1)
8
  {
9
    // zu viele Overflows ?
10
    if( NrOverflows > MEINE_GRENZE )
11
    {
12
       ....
13
    }
14

15
    //
16
    // liegt eine vollst�ndige Messung vor?
17
    //
18
    if( UpdateUart)
19
    {
20
      ...

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