Forum: Mikrocontroller und Digitale Elektronik Drehzahlmesser / Frequenzmesser spinnt?


von F. K. (digitalone)


Angehängte Dateien:

Lesenswert?

Hallo zusammen, nachdem ich schon öfter hier mitgelesen habe musste ich 
mich nun anmelden da ich bei der Programmierung eines Drehzahlmessers 
mit einem Atmega32 auf folgendes Problem gestossen bin und nicht weiter 
komme. So wie es aussieht zählt mein ICP Zähler die richtige Anzahl Tics 
macht jedoch bei der Umrechnung in 1/min Fehler. Das passiert jedoch 
erst ab einer gewissen Anzahl Tics nicht aber bei 56535 was ja auf ein 
int16 Überlauf hinweisen würde sondern erst bei höheren Werten.

Die Ausgegebenen Daten sehen z.B. so aus:

Tics   -     1/min
16696  -    7107
24695  -    4859
32695  -    3670
40700  -    2948
48700  -    2464
56702  -    2116
64698  -    1854
78998  -    15191  anstatt  1519
86992  -    13794  anstatt  1379

Hat jemand eine Idee woran das liegen kann? Habe ich irgendwas 
übersehen?

Vielen Dank im Voraus.

digitalone

von Stefan B. (stefan) Benutzerseite


Lesenswert?

F. K. schrieb:

> Das passiert jedoch
> erst ab einer gewissen Anzahl Tics nicht aber bei 56535 was ja auf ein
                                                    ^^
> int16 Überlauf hinweisen würde sondern erst bei höheren Werten.

uint16_t
65535
^^

int16_t
32767

von F. K. (digitalone)


Lesenswert?

Du hast Recht es müsste natürlich uint16_t Überlauf heißen aber das 
hilft jetzt leider nicht.

von Karl H. (kbuchegg)


Lesenswert?

Ich seh auch kein ursächliches Problem

Aber ich würde erst mal:

  uint64_t drehzahl=0;

kein Grund das als uint64_t zumachen. Das ist nur Beschäftigungstherapie 
für den µC

   char temp2[6],temp3[6];
die sind ein wenig arg knapp. Bei solchen char-Felder: Nicht kleckern, 
klotzen. Auch wenn du nur mit maximal 5 stelligen Zahlen rechnest, es 
schadet nichts, diese Felder auf 10 oder 15 zu vergrößern. Und wenn dann 
eine Zahl doch einmal etwas größer wird, hat man ein wenig Reserve.


78998  -    15191  anstatt  1519
86992  -    13794  anstatt  1379

Das da ziemlich genau das 10-fache rauskommt, lässt mich nicht an einen 
Rechenfehler glauben, sondern an ein Anzeigeproblem, zb. Zahlen die 
nicht vollständig von der nächsten überschrieben werden. Aber so wie du 
das aufgebaut hast, kann es das eigentlich auch nicht sein.

von F. K. (digitalone)


Lesenswert?

uint64_t drehzahl=0; hatte ich auch schon auf 32 habe es nur testweise 
hochgesetzt. Die char hatte ich auch schon 20 lang - kein Unterschied.
Habe das ganze auch mal rechnen lassen mit 78998 als Festwert für Tics 
dann zeigt er richtig an. Deswegen bezweifel ich dass es an der Anzeige 
liegt. Bin nur erstmal beruhigt dass euch auf den ersten Blick auch 
nichts auffällt aber vielleicht kommt ja noch jmd. drauf.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

F. K. schrieb:

> 78998  -    15191  anstatt  1519
> 86992  -    13794  anstatt  1379
                  ^               ^

Da fehlt eine Stelle, also eventuell Bufferoverflow, wenn uint64_t 
drehzahl an ultoa() übergeben wird.

Ich würde versuchsweise temp2 größer machen, damit die abschliessende 
0 nicht verloren geht. Und ich würde auch mal drehzahl uint32_t 
machen.

> u64_drehzahl=((2000000/60)/u32_tics);

Hmm...

u64_drehzahl = ((uint64_t)2000000 / 60) / u32_tics;

Mit uint32_t:

drehzahl = (2000000UL / 60) / tics;

von Stefan B. (stefan) Benutzerseite


Lesenswert?

F. K. schrieb:

> Habe das ganze auch mal rechnen lassen mit 78998 als Festwert für Tics
> dann zeigt er richtig an. Deswegen bezweifel ich dass es an der Anzeige
> liegt.

Wird tics richtig berechnet?

>>    u32_tics = u16_zaehler - u16_zaehler_alt;

u32_tics = (uint32_t)u16_zaehler - u16_zaehler_alt;

Oder gemessen?

Was machst du, wenn u8_overflow_status == 1 ist? Du müsstest doch dann 
65536 auf u16_zaehler addieren!

von Karl H. (kbuchegg)


Lesenswert?

Ich kann deine ganze Berechnung nicht nachvollziehen

78998  -    15191  anstatt  1519
86992  -    13794  anstatt  1379

mit der Berechnung
          drehzahl=((2000000/60)/tics);
und einem Taschenrechner kriege ich ganz andere Ergebnisse raus.

2000000/60 -> 33333

78998   ->   33333 / 78998  -> 0

Was'n jetzt los?
Zeigst du uns ein anderes Programm, als das was tatsächlich läuft?

Ganz abgesehen davon, dass tics als Differenz zweier unsigned 16 Bit 
Werte gar nicht 78998 sein kann! Bei 65535 ist in deinem Code Schluss.

**************************************
-> du hast den falschen Code gepostet!
**************************************

von F. K. (digitalone)


Lesenswert?

da ist mir beim zurückbauen meines Versuchscodes ein Fehler unterlaufen 
es muss natürlich heißen u64_drehzahl=((2000000*60)/u32_tics);
bzw. jetzt u32_drehzahl=((2000000*60)/u32_tics); alos MAL 60 nicht 
GETEILT durch 60.

Der Fehler ist natürlich weiterhin vorhanden.

von F. K. (digitalone)


Lesenswert?

> Ganz abgesehen davon, dass tics als Differenz zweier unsigned 16 Bit
> Werte gar nicht 78998 sein kann! Bei 65535 ist in deinem Code Schluss.
>
> **************************************
> -> du hast den falschen Code gepostet!
> **************************************

Das habe ich auch gedacht aber es funktioniert so da wird wohl intern 
mit overflow bit gerechnet werden!?

von Karl H. (kbuchegg)


Lesenswert?

> Habe das ganze auch mal rechnen lassen mit 78998 als Festwert für Tics
> dann zeigt er richtig an.

Dann würde ich mal ganz stark die Korrektheit der Ausgabe für ticks 
bezweifeln. Dort nach dem rechten sehen.
Zählerwerte ausgeben, Anzahl Overflows ausgeben, Berechnungen 
kontrollieren, etc.

von Karl H. (kbuchegg)


Lesenswert?

F. K. schrieb:
>> Ganz abgesehen davon, dass tics als Differenz zweier unsigned 16 Bit
>> Werte gar nicht 78998 sein kann! Bei 65535 ist in deinem Code Schluss.
>>
>> **************************************
>> -> du hast den falschen Code gepostet!
>> **************************************
>
> Das habe ich auch gedacht aber es funktioniert so da wird wohl intern
> mit overflow bit gerechnet werden!?

Nicht mit deinem geposteten Code.
Die Differenz zweier unsigned 16 Bit Zahlen kann nie größer als 65535 
sein. Wenn du was anderes schaffst, solltest du sofort einen Vertrag mit 
Las Vegas abschliessen, denn dann ist der Copperfield ein popeliger 
Trickbetrüger gegen dich.

Dieser Ausdruck hier
1
volatile uint16_t zaehler_alt=0,zaehler=0;
2
3
...
4
5
    tics = zaehler - zaehler_alt;

kann nie größer als 65535 werden. Völlig unmöglich.

von Karl H. (kbuchegg)


Lesenswert?

Ich würde vorschlagen.

Du stellst jetzt in deinem Code wieder die ursprüngliche Version her. So 
wie sie richtig ist und wie du denkst dass es sein müsste. drehzahl 
machst du als uint32_t und die beiden char-Felder setzt du größer. Dann 
kontrollierst du noch ob der Fehler immer noch da ist und notierst dir 
die Ausgaben.
An besten veränderst du auch die Ausgabe ganz leicht, so dass du sicher 
sein kannst, dass es genau dieser Code und kein anderer ist, der auf dem 
µC läuft.

Dann postest du Code und Zahlen


(Ich traue deinem Code nicht mehr. Sobald ich dich einmal dabei erwischt 
habe, dass der gepostete Code nicht dem entspricht der den Fehler zeigt, 
will ich es ganz genau wissen)

von F. K. (digitalone)


Lesenswert?

> Dieser Ausdruck hier
>
>
1
> volatile uint16_t zaehler_alt=0,zaehler=0;
2
3
>     tics = zaehler - zaehler_alt;
4
>
>
> kann nie größer als 65535 werden. Völlig unmöglich.

Mhmm das hab ich mir vorher auch gedacht dachte dann durch das Programm 
eines besseren belehrt worden zu sein. Aber wenn das nicht funktioniert 
gilt es ja eigentlich nur den Fehler zu finden wie er auf die Werte über 
65535 kommt und wieso er in der Berechnung auf einmal so einen Sprung 
macht.

von F. K. (digitalone)


Lesenswert?

Alles klar ich werde jetzt mal eben Pause machen und dann alles nochmal 
überarbeiten und reinstellen. Bis später.

von Karl H. (kbuchegg)


Lesenswert?

Eine Idee hab ich noch

Verändere das mal
1
    lcd_puts("tics=");
2
    ultoa (tics,temp3,10);
3
    set_cursor(6, 4);
4
    lcd_puts(temp3);
5
    lcd_puts("*");     // <- der ist neu

Ich vermute du hast gar keine 78998 Ticks. Du hast nur 7899 Ticks und 
die abschliessende 8 ist ein Überbleibsel von früher, welches nie 
gelöscht wurde. Der * soll das anzeigen, indem er klar macht, wo die 
Zahl wirklich aufhört.

Auf jeden Fall würde das alles erklären:
   7899 ist im möglichen Zahlenbereich
   Die Berechnung für 7899 ergibt tatsächlich 15191

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 78998  -    15191  anstatt  1519
> 86992  -    13794  anstatt  1379
steht da noch Müll von vorher auf dem Display und wird nicht 
überschrieben (die 1 bei 1519_1 bzw. die 4 bei 1379_4)?

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:
>> 78998  -    15191  anstatt  1519
>> 86992  -    13794  anstatt  1379
> steht da noch Müll von vorher auf dem Display und wird nicht
> überschrieben (die 1 bei 1519_1 bzw. die 4 bei 1379_4)?

Bei den Drehzahlen nicht. Das hat er relativ geschickt gelöst. Aber bei 
den Ticks! Ich denke dort ist noch Müll von vorhergehenden Durchläufen.

von Thilo M. (Gast)


Lesenswert?

Hier mal eine ältere (aber bewährte) Version von mir:
1
SIGNAL (SIG_INPUT_CAPTURE1)    // Frequenzmessung
2
{
3
  if (!(Status &(1<<ST_ICP)))
4
  {
5
     starttime = ICR1;
6
     ICP_OVF = 0;
7
     Status |= _BV(ST_ICP);
8
     return;
9
  }
10
  else
11
  {
12
     stoptime = ICR1;
13
     Frequenz = (ICP_OVF * 65536) + stoptime - starttime;// Zählerstand ermitteln
14
     Frequenz = (16000000/Frequenz);  // SYSCLK*16MHz 
15
     Status &= ~_BV(ST_ICP);    // Frequenz berechnen
16
    TIFR |= _BV(ICF1);
17
  }
18
}

Vielleicht kannst du was 'rauslesen. ;-)

von F. K. (digitalone)


Lesenswert?

> Verändere das mal
>
>
1
>     lcd_puts("tics=");
2
>     ultoa (tics,temp3,10);
3
>     set_cursor(6, 4);
4
>     lcd_puts(temp3);
5
>     lcd_puts("*");     // <- der ist neu
6
>
>
> Ich vermute du hast gar keine 78998 Ticks. Du hast nur 7899 Ticks und
> die abschliessende 8 ist ein Überbleibsel von früher, welches nie
> gelöscht wurde. Der * soll das anzeigen, indem er klar macht, wo die
> Zahl wirklich aufhört.
>
> Auf jeden Fall würde das alles erklären:
>    7899 ist im möglichen Zahlenbereich
>    Die Berechnung für 7899 ergibt tatsächlich 15191

Das war der entscheidende Tip!!! Danke

Jetzt muss ich es nurnoch hinbekommen dass er mir zuverlässig im Falle 
eines Überlaufes zu den tics overflow_status*65536 hinzuaddiert. Zurzeit 
springt er mir leider noch hin und her zwischen mit und ohne 65536...

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.