Forum: Mikrocontroller und Digitale Elektronik Int mit float multiplizieren


von Freq_Messung (Gast)


Lesenswert?

Hey ich möchte per µC (ATMega 64) eine Frequenz Messen. Ich arbeite mit 
AVR Studio 4.

Meine Idee war es ich starte per Flanke an einem Port Pin einen 8-Bit 
Timer der bei überlauf per Interrupt eine Variable hochzählt. Bei der 
nächsten Flanke soll der Timer gestoppt werden. (Ich weis ihr würdet das 
bestimmt anders lösen aber das ist auch erstmal nicht das Problem). 
Anschließend reche ich mir den gesamten Timerwert aus und speicher den 
Wert in einer INT Variable. Diese will ich anschließend mit einer Float 
multiplizieren und wieder in eine Float abspeichern. Und da liegt das 
Probelm bei der Simulation springt er da komplet aus dem Programm raus. 
Habt ihr eine erklärung wieso?



1
float CPUT=0.0000000625;
2
int T0OF=0;
3
float periodendauer=0.0;
4
int freq=0;
5
6
int main(void)
7
{
8
reg_init();        //Initialisierung von den Registern
9
port_config();      //Ports konfigurieren
10
sei();           //Globale Interrupt Enable
11
char string[8]="0";
12
13
14
while(1)
15
{
16
17
18
/*Vorheriger Code wurd ausgeschnitten. Funktion wurde einzeln geprüft und erwiesen keine Fehler*/
19
20
21
T0OF=8000;//Beispielwert für den gesamten Timerwert
22
23
periodendauer=T0OF*CPUT;/*<<<--- An dieser Stelle verlässt die Simulation das Programm*/
24
freq=1/periodendauer;
25
26
27
/*weiterer unkritischer Code zum senden eines Strings per RS232*/
28
29
T0OF=0;
30
freq=0;
31
32
}
33
34
return 0;
35
}



Ich hoffe ihr habt einen Rat für mich. Bitte bezieht euch auf das 
Problem. Dankeschön Grüße

von Daniel V. (danvet)


Lesenswert?

Was passiert, wenn "periodendauer" Null ist?

von Freq_Messung (Gast)


Lesenswert?

Naja eigenklich würde er dan druch fehler rausspringen da division durch 
0 nicht möglich ist. Aber er spring ja schon vorherraus und 
8000*0.0000000625 ist doch nicht 0 von daher sollte das doch bei diesem 
Beispeil kein Problem sein oder? ansonsten geb ich periodendauer gern 
einen Wert vor.

von Pieter (Gast)


Lesenswert?

moin moin,

eventuell ist float ein Problem.

Einfach mal
periodendauer=TOOF* 1E6 / 16
rechnen lassen.

>>freq=1/periodendauer;
das wird bestimmt auch nicht.

MfG
Pieter

von Freq_Messung (Gast)


Lesenswert?

Hey danke für dne Tipp.

Die kleinste Frequenz ist ca 2kHz. Der Timer der eine Taktfreqeunz von 
16Mhz hat würde dan einen maximalen Timerwert von 8000 haben.

1/16.000.000=0.0000000625

1/2.000=0.0005

0.0005/0.0000000625=8000

Richtig?

Wenn ich dan weiterrechne mit der Formel von Pieter erhalte ich

8000*1.000.000/16=500.000.000

Aber was dann? Ich muss doch irgentwo über ein 1/ gehen um eine Frequenz 
daraus zu erhalten oder? Wie schließe ich aus den 500.000.000 wieder 
zurück auf 2.000Hz?

von Steel (Gast)


Lesenswert?

Er wird nicht vorher rausspringen.

Versuchs mal so:
1
periodendauer=(float)T0OF*CPUT;
2
freq=(int)(1.0/periodendauer);

von Freq_Messung (Gast)


Lesenswert?

Steel bei deinen 2 Rechnungen spring er auch direkt raus.
1
  T0OF=8000;
2
  
3
  periodendauer=T0OF*1E6/16;
4
  zwischens=periodendauer/1E12;
5
  freq=1/zwischens;

periodendauer wird wie in der rechnung auf 500.000.000 und auch 
zwischens geht nach derrechnugn auf die 0.0005

aber bei freq=1/0.0005 spchreibt er mir immer eine 1 in freq rein

von Ralf G. (ralg)


Lesenswert?

link mal die mathe-lib mit dazu!

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Hi,

brauchst du die Periodendauer denn noch?
Wenn nicht, was spricht dagegen
1
float CPUT=16e6; // 1/0.0000000625;
2
freq = CPUT/T0OF;

von Freq_Messung (Gast)


Lesenswert?

@ Ralf
Math lib ist verlinkt und es ergibt trozdem bei der Rechnung 
freq=1/zwischens immer noch 1


@Christopher
1
float CPUT=16e6; // 1/0.0000000625;
2
freq = CPUT/T0OF;


freq=CPUT/T0OF was soll mir das genau bringen?

0.0000000625/8000 dadurch komme ich auch nicht auf die Frequenz oder hab 
ich iwo ein Denkfehler?


Aber nein die Periodendauer wird auch nur als Zwischenschritt benötigt 
und wird nicht weiter verwendet.

von Freq_Messung (Gast)


Lesenswert?

Entschuldigung. Mein Fehler natürlich würde 16E6/ den Timerwert auf die 
Frequenz bringen. Ich hab mich verlesen

von Ralf G. (ralg)


Angehängte Dateien:

Lesenswert?

also bei mir funktioniert's.

von Freq_Messung (Gast)


Lesenswert?

Das Programm/Die Umrechung läuft jetzt. Danke für euche Hilfe. Ich werde 
dne COntroller mal anschließen und schaun ob der vernümpftig arbeitet. 
Fals es doch noch was gibt werdet ihr villeicht nochmal von mir hören :) 
Danke

von Freq_Messung (Gast)


Lesenswert?

@ Ralf
Bei mir leider nicht ich weis nicht woran es liegt.

Aber die andere Version funktioniert ja jetzt.

Jetzt habe ich aber das Problem das der Messwert einfach nicht stimmt 
und der COntroller nur Müll ruaswirft.

Ich warte auf die Flanke an dem Pin und starte darauf hin den 8 Bit 
Timer. Wenn die nächste Flanke kommt Stoppe ich den wieder und werte den 
Gesamten Timerstand aus. Das passt aber garnicht die Wert im 
Hyperterminal springne hin und er und sind nicht stabil. Hier mal der 
Code bitte macht mich nicht fertig man das so nicht macht ^^ bin noch 
relativer Anfänger.
1
int main(void)
2
{
3
  reg_init();        //Initialisierung von den Registern
4
  port_config();      //Ports konfigurieren
5
  sei();           //Globale Interrupt Enable
6
  char string[10]="0";
7
8
9
  while(1)
10
  {
11
    TCNT0=0;
12
    T0OF=0;
13
    freq=0;
14
    _delay_ms(1000);
15
    while(PINA>0);
16
    while(PINA==0);
17
    
18
    TCCR0=0x01;//Timer mit CPU Takt starten
19
20
    while(PINA>0);
21
    while(PINA==0);
22
    TCCR0=0x00;//Timer stoppen
23
  
24
    T0OF=T0OF*255;
25
    T0OF=T0OF+TCNT0;
26
27
    freq=16E6/T0OF;
28
29
    zt=freq/10000;
30
    freq=freq%10000;
31
32
    t=freq/1000;
33
    freq=freq%1000;
34
35
    h=freq/100;
36
    freq=freq%100;
37
38
    z=freq/10;
39
    freq=freq%10;
40
41
    e=freq;
42
43
    /*Anpassung an die ASCII Tabelle*/
44
    zt=zt+0x30;
45
    t=t+0x30;
46
    h=h+0x30;
47
    z=z+0x30;
48
    e=e+0x30;
49
50
    /*Werte in einen String schreiben*/
51
    string[0]=zt;
52
    string[1]=t;
53
    string[2]=h;
54
    string[3]=z;
55
    string[4]=e;
56
    string[5]=' ';
57
    string[6]='H';
58
    string[7]='z';
59
    string[8]=0x0A;;
60
    string[9]=0x0D;
61
62
    /*Stringlaenge auslesen und String senden*/
63
    stringlaenge=sizeof(string);
64
    string_senden(string);
65
66
  
67
  }
68
69
  return 0;
70
}


Das Senden des Strings funktioniert. Das benutze ich auch schon seit ein 
paar Programmen.

Meine Frequenzmessung muss nicht auf 1 Hz genau sein. 10 Hz würden 
locker reichen.

Wie gesagt die Erfassung ist warscheinlich totaler Müll mir ist aber in 
dem Moment nix besseres eingefallen.

von Jim M. (turboj)


Lesenswert?

Versuch mal mal:
1
volatile int T0OF

von Freq_Messung (Gast)


Lesenswert?

Guten Morgen. Hab es gestern nicht mehr geschafft etas auszuprobieren

@Jim Meba
volatile int T0OF

funktioniert auch nicht. Im Hyperterminal wirft er irgentwelche Zahlen 
zwischen 0Hz und ca. 65000 Hz. Wenn der ausgegebene Wert wenigstens 
stabil wäre könnte es ein Rechenfehler sein. Der springt aber immer 
lustig hin und her. Mal 900Hz mal 22054Hz und dan auch ma wieder 
64000Hz.

Lieg wahrscheinlich an meiner Erfassung.

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Hi,

von was willst du überhaupt die Frequenz messen? Vielleicht liegt da ja 
schon der Fehler

von Freq_Messung (Gast)


Lesenswert?

Ich erzeuge mit einem NE555 ein PWM/Frequenz die entkoppel ich mittels 
Optokoppler. Auf dem Oszilloskop ist die Frequnz bis auf wenige Hz 
stabil.

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.