Drehzahlmesser / Frequenzmesser spinnt?

OP #1700242
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
Angehängte Dateien:
#1700264
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.
OP #1700281
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.
Persönliche Seite #1700282
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;
Persönliche Seite #1700293
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!
#1700294
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!
**************************************
OP #1700300
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!?
#1700303
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.
#1700307
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.
#1700321
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)
OP #1700324
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.
#1700333
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
Gast #1700344
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. ;-)
OP #1700558
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...

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