Interruptserviceroutine

Gast #4694923
Lesenswert?

Hallo,

ich hätte eine Frage zum folgenden Link:

http://rn-wissen.de/wiki/index.php/Servos#Siehe_auch

ISR(TIMER2_COMP_vect)
{
  static int count;
  if(count>servopos)SERVOPORT&=~(1<<SERVOPIN);
    else SERVOPORT|=(1<<SERVOPIN);
  if(count<2000)count++; // Die Impulse sollten alle 20ms gesendet 
werden! 6.2.11 mic
    else count=0;
};

Ich verstehe was ein Sevo ist und die wie die dieser funktioniert (f=50 
Hz, Periodenlänge 20ms, Impulsbreite zwischen 1ms und 2ms, usw). Ich 
komme nur nicht drauf wie die 2000 (20ms) berrechnet wurde.

if(count<2000)count++; ??????


Danke
Gast #4694996
Lesenswert?

in dem genannten Link steht auch noch:
1
void servo_init()
2
{
3
  TIMSK|=(1<<OCIE2);
4
  TCCR2 |= (1<<WGM21) | (1<<CS20);  //Prescale=1, CTC mode
5
  OCR2 = F_CPU/100000;      //alle 10µS ein IRQ
6
  DDRSERVO|=(1<<SERVOPIN);
7
};

Wenn alle 10µs ein Timer-Interrupt kommt, man in jedem Interrupt um eins 
hochzählt und das 2000 mal tut, dann sind das 2000*10µs = 20ms.
Gast #4695298
Lesenswert?

Danke.
Ich habe nun versucht ein PWM-Signal am Pin des Controllers zu erzeugen.
Wenn ich den Pin des Controller am Oszillokop anschließe, sehe ich nur 
in Strich und erkenne da keinen Impuls (Pulsbreite 10ms). Ich finde den 
Fehler im Code nicht? Danke

/*----Timer2-----CTC-Modus----
8-Bit Timer: 0...255
Prescaler: 64
F_CPU/Prescaler: 16MHz/64=250000 Takte/s
Alle 1ms soll ein Interrupt ausgelöst werden
Periodenlänge 30ms
-->OCR2A=250000*1ms=249
*/

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>


//globale Variable
volatile uint8_t count;
void Timer2_init(void);


int main(void)
{
//PB1 als Ausgang setzen
DDRB|=(1<<PB1);
//Pin PB1 auf High setzen
PORTB|=(1<<PB1);

Timer2_init();
while(1)
{
} return 0;
}

void Timer2_init(void)
{
//Mode 4: CTC-Modus
TCCR2A|=(1<<WGM21);
//Prescaler 64
TCCR2B|=(1<<CS22);
//Der Vergleichswert beträgt 249
OCR2A=249;
//Interrupt aktivieren
TIMSK2|=(1<<OCIE2A);
sei();
}

ISR(Timer2_COMPA_vect)
{
    if(count<10)
    PORTB|=(1<<PB1);
    else
    PORTB&=~(1<<PB1);

    if(count<30)
    count++;
    else
    count=0;
}
Gast #4695309
Lesenswert?

Versuch erstmal, in der main in einer Endlosschleife ohne 
Timer-Interrupt den IO-Pin zu toggeln, mit Delay-Counterschleifen 
dazwischen (den counter als globales volatile deklarieren nicht 
vergessen).

Dann weißt Du schonmal, ob das Problem in der IO-Initialisierung oder im 
Aufsetzen des Timer-Interrupts liegt.
Gast #4695320
Lesenswert?

Nop schrieb:
> Wenn alle 10µs ein Timer-Interrupt kommt, man in jedem Interrupt um eins
> hochzählt und das 2000 mal tut, dann sind das 2000*10µs = 20ms.

Wenn man alle 10µs versucht, einen Timer-Interrupt zu feuern, würde ich 
erstmal ganz gründlich gucken, ob der Prozessor das vernünftig schafft 
und sich nicht die Interrupts auf die Füße treten. Mindestens wenn der 
µC auch noch andere Dinge erledigen soll, kann das sehr eng werden.
Gast #4695338
Lesenswert?

Chilitester schrieb:
> .... würde ich erst mal gucken ob das jemand überhaupt
> braucht. Zum Servo-Steuern sicherlich nicht.

Zum Steuern eines Servos würde es sicher reichen, wenn man z.B. einen 
1ms System-Interrupt laufen hat, der dann für die 20ms Periodendauer 
gezählt wird und einen 8-Bit Timer, quasi als Monoflop, zur Erzeugung 
des Steuerimpulses.
Dann müßte man sich nur noch eine Beschäftigung für den Prozessor 
überlegen, damit der sich nicht zu Tode langweilt ;-)
Gast #4695689
Lesenswert?

Dani schrieb:
> Jetzt wollte ich Soft-PWM (Timer2 Interrupt) anwenden

Du hast es aber mit 2 Zeiten zu tun: 20 ms Basis, davon x ms PWM-Impuls. 
Dazu brauchst du 2 Timer, einen für 20 ms und einen zweiten, der vom 
ersten gestartet wird und die variablen 0..20 ms für die Impulslänge 
ausgibt. Es sei denn es gibt zusätzliche Hardware wie Caption-Register.

Oder du programmierst einen Timer abwechselnd mit x ms (PWM ein) und 20 
- x ms (PWM aus), das ist aber weniger genau. Man kann aber die 
Verzögerung zum Wiederstarten des Timers einrechnen.

Heutige Controller verfügen ja über ganze Timer-Rudel.

Georg
Gast #4696009
Lesenswert?

Georg schrieb:
> Dani schrieb:
>> Jetzt wollte ich Soft-PWM (Timer2 Interrupt) anwenden
>
> Du hast es aber mit 2 Zeiten zu tun: 20 ms Basis, davon x ms PWM-Impuls.
> Dazu brauchst du 2 Timer, einen für 20 ms und einen zweiten, der vom
> ersten gestartet wird und die variablen 0..20 ms für die Impulslänge
> ausgibt. Es sei denn es gibt zusätzliche Hardware wie Caption-Register.
>
> Oder du programmierst einen Timer abwechselnd mit x ms (PWM ein) und 20
> - x ms (PWM aus), das ist aber weniger genau. Man kann aber die
> Verzögerung zum Wiederstarten des Timers einrechnen.
>
> Heutige Controller verfügen ja über ganze Timer-Rudel.
>
> Georg

Ich dachte in der ISR Routine habe ich  bereits shon die Zeit definiert, 
in denen ein Pin auf High bzw. Low gesetzt wird.

ISR(Timer2_COMPA_vect)
{
    if(count<10)
    PORTB|=(1<<PB1);
    else
    PORTB&=~(1<<PB1);

    if(count<30)
    count++;
    else
    count=0;
}
Gast #4696272
Lesenswert?

Wenn man schon fremde Sourcen zitiert sollte man wenigstens auf die 
Quelle verweisen:
https://www.proggen.org/doku.php?id=electronics:projects:legorobot

Wolfgang schrieb:
> Wenn man alle 10µs versucht, einen Timer-Interrupt zu feuern, würde ich
> erstmal ganz gründlich gucken, ob der Prozessor das vernünftig schafft
> und sich nicht die Interrupts auf die Füße treten.

Bei 4MHz geht es nicht (hat Karl Heinz vor Jahren schon rausgefunden). 
Bei 8MHz geht es wohl. Beim Lego Roboter sind es 16MHz.

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