Forum: Mikrocontroller und Digitale Elektronik Atmega8 Frequenzein-ausgang


von denver2013 (Gast)


Lesenswert?

Hallo,
ich brauche ein wenig Hilfe.
Mein Programm soll folgendes machen:
Die Eingangsfrequenz (INT1) bewegt sich im Bereich von ca. 30-300 Hz.
Die Ausgangsfrequenz (wackeln an beliebigem Pin) bis ca. 20-30% +/- .
Das Problem ist, es kommen immer wieder Aussetzer in unregelmäßigen 
Abständen (mit Osci kontr.).
Vermutlich Timereinstellungen.
Wer hat einen Tip?
1
// Atmega8
2
// Timer1 Timer2 16Mhz Clock
3
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <math.h>
8
9
volatile int Takt;
10
int T2;
11
volatile double Eingang;
12
volatile double x = (-0.9916);
13
int main(void)
14
{
15
   TCCR2 |= (1 << WGM21); //CTC Timer2
16
17
   GICR  |= (1<<INT1);
18
   MCUCR |= (1<<ISC10) | (0<<ISC11); //Any logical change on INT1 generates
19
                                      // an interrupt request.
20
21
   TIMSK |= (1 << OCIE2) | (1<<OCIE1A); //Interrupt compare match Timer1+2
22
 
23
24
25
   TCCR2 |= (1 << CS22) | (1 << CS21) | (1 << CS20); //Priscaler 1024 Timer2
26
 
27
28
   TCCR1B |= (1 << WGM12);                //CTC Timer1
29
   TCCR1B |= (1 << CS11) | (1 << CS10);   // Prescaler 64
30
   sei(); // enable interrupts
31
    
32
33
DDRB |= (1 << PB1);
34
35
    while (1);
36
    {
37
    ; // Die Berechnung hier bringt nur Hausnummern ?????
38
    }
39
}
40
41
ISR(INT1_vect)
42
   { 
43
    Takt++;
44
  
45
   }
46
47
ISR (TIMER2_COMP_vect)
48
{
49
    T2++;
50
     if (T2 == 30) //~61 = 1 Sekunde
51
    {
52
      Eingang = Takt;
53
    Takt = 0;
54
    T2 = 0;    
55
    OCR1A = (pow( Eingang, x )*120221); //y = 120221x-0,9916
56
    }
57
  
58
}
59
60
61
ISR(TIMER1_COMPA_vect)
62
{
63
  PORTB ^= (1 << PB1);
64
}

von Uwe (de0508)


Lesenswert?

Den gewohnten Doubledatentype hat du nicht als Zahlenbereich beim avr 
gcc.

Es gilt in ISR macht man nur das nötigste, das was schnell abgearbeitet 
wird.

Aber in deinem code steht solch ein Monster:
1
OCR1A = (pow( Eingang, x )*120221);

Gibt bitte mal eine Schätzung über das Zeitverhalten ab und dann 
schreibe ein neues Programm - Test - um die Laufzeit mit einem Timer zu 
messen.
Du wirst Dich wundern !

Also wenn solch eine Berechnung, dann im Main.

Ich will jetzt gar nicht auf die Umgehung des Datentype double ein 
gehen, das geht !

Das werden andere noch mache - Stichwort Fixpoint Interger Mathematik.

von denver2013 (Gast)


Lesenswert?

@Uwe S.

Den Komentar in meinem Programm hast Du aber schon gelesen?
 // Die Berechnung hier bringt nur Hausnummern ?????

Vielleicht soll ich noch anfügen ich mach das Ganze nur aus Spaß an der 
Freud.
Leider hilft mir Dein Beitrag nicht weiter.
Trotzdem vielen Dank.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

denver2013 schrieb:
> T2++;
>      if (T2 == 30) //~61 = 1 Sekunde
>     {
>       Eingang = Takt;
>     Takt = 0;
>     T2 = 0;

Da fallen mir (abgesehen vom double Datentyp) mehrere Sachen auf:
* T2 ist nicht als volatile deklariert und dann auch noch als int. Hier 
reicht ein uint8_t (es wird ja höchstens bis 30 gezählt), damit 
entfallen alle Überlegungen hinsichtlich atomarer Zugriffe.
> ISR(INT1_vect)
>    {
>     Takt++;
>
>    }
* Takt ist immer eine Ganzzahl, deswegen ist es auch hier überflüssig, 
double zu benutzen. Abgesehen davon ist ein double ein so langer 
Datentyp, das hier unbedingt auf 'atomare' Zugriffe zu achten wäre.

Grundsätzlich gilt, das kleine MCs immer sehr viel Zeit brauchen, um 
Gleitkommazahlen zu behandeln. Mach am besten die gesamte Berechnung mit 
ganzen Zahlen und rechne sie nur am Schluss in die gewünschten Anzeige 
um.

von amateur (Gast)


Lesenswert?

@denver2013

Bist Du sicher, dass Du an der richtigen Stelle nach Fehlern und 
Problemen suchst?

Wenn Du festgestellt hast:
>    ; // Die Berechnung hier bringt nur Hausnummern ?????
solltest Du nicht den Rechenort verlegen, sondern nach dem Warum suchen.

von denver2013 (Gast)


Lesenswert?

@amateur

Ich hab schon alle "Rechenorte" ausprobiert leider ohne Erfolg :-(

von Wolfgang (Gast)


Lesenswert?

denver2013 schrieb:
> Ich hab schon alle "Rechenorte" ausprobiert leider ohne Erfolg :-(

Eben, darin liegt es dann wohl nicht.

Uwe S. schrieb:
> Aber in deinem code steht solch ein Monster:
> OCR1A = (pow( Eingang, x )*120221);
> Gibt bitte mal eine Schätzung über das Zeitverhalten ab und dann
> schreibe ein neues Programm - Test - um die Laufzeit mit einem Timer zu
> messen.

denver2013 schrieb:
> Leider hilft mir Dein Beitrag nicht weiter.

Auf Deutsch: Guck dir mal die Rechenzeit für die Operation zur Belegung 
des OCR1A an und setze das in Relation zum Abstand der Interupts

von denver2013 (Gast)


Lesenswert?

Vielen Dank an Alle.
Es funktioniert.

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.