Forum: Mikrocontroller und Digitale Elektronik Probleme mit PPM Signal


von Andreas (Gast)


Lesenswert?

Hallo Leute,

ich bin gerade dabei einen Mortorregler für ein Modellflugzeug zu bauen.
Die Schaltung ließt dazu ein PPM Signal ein und gibt ein PWM Signal für 
einen
DC Motor aus.

Wenn ich den Gasknüppel von der "Aus" Position langsam nach vorne 
schiebe, dann funktioniert alles erstmal prima. Ab einem gewissen Wert 
"springt" das eingelesene Signal (also thrust) schlagartig um etwa 15 
nach oben. Wenn ich weiter Gas gebe, springt er wieder zurück und 
funktioniert wieder ein bisschen, bis er erneut springt und so weiter. 
Interesannterweise sind die Sprünge immer an den selben Stellen (also 
bei der selben Schalterstellung).

Ich vermute mal, dass es mit dem überlauf des 8Bit-Timers zusammenhängt 
(Den 16er brauche ich für die PWM), aber ich komme nicht drauf, was 
genau es ist.
Vllt. fällt euch was ein?
(Und bei the way: wird TCNT0 automatisch auf 0 gesetzt, wenn der Timer 
wieder startet?)


1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
void long_delay(int ms) {
6
  
7
    for(; ms>0; ms--) _delay_ms(1);
8
}
9
10
11
volatile int up = 0;
12
volatile int overtime = 0;
13
volatile double thrust = 0;
14
15
ISR(INT0_vect){
16
17
  if(up == 0){
18
    TCCR0 |= (1 << CS00);
19
    up = 1;
20
    MCUCR &= ~(1 << ISC00);
21
  }else{
22
    TCCR0 = 0;
23
    thrust = ((overtime*256 + TCNT0) -9300)/23.6;
24
    TCNT0 = 0;
25
    overtime = 0;
26
    MCUCR |= (1 << ISC00);
27
    up = 0;  
28
  }  
29
  
30
}
31
32
ISR (TIMER0_OVF_vect)
33
{
34
  overtime++;
35
}
36
 
37
int main()
38
{
39
  //PWM Init
40
  DDRB |= (1 << PB1);
41
  TCCR1A |= (1 << WGM10);
42
  TCCR1A |= (1 << COM1A1);
43
  TCCR1B =  (1<<CS10) | (1<<CS11);
44
  
45
  //Interrupt Init
46
  GICR |= (1 << INT0);
47
  MCUCR |= (1 << ISC01);
48
  MCUCR |= (1 << ISC00);
49
  
50
  TIMSK |= (1<<TOIE0);
51
  
52
  sei();
53
54
  
55
  while(1<2){
56
  
57
    int mthrust = (int)thrust;
58
    if(mthrust < 0){
59
      mthrust = 0;
60
    }
61
    if(mthrust > 255){
62
      mthrust = 255;
63
    }
64
    
65
    OCR1A = mthrust;
66
    
67
  }
68
69
}


Vielen Dank im Vorraus
Andi

von Purzel H. (hacky)


Lesenswert?

Schon mal den simulator probiert ?

von Peter B. (pbuenger)


Lesenswert?

Hai Andi,

Dein Programm hat einen entscheidenden Fehler: Wenn innerhalb der 
Interrupt-Routine INT0_vect der Timer überläuft, dann liest Du Müll 
zurück. Das Low-Byte aus TCNT0 ist schon übergelaufen, der Hilfszähler 
overtime für das High-Byte aber noch nicht, weil die TIMER0_OVF_vect 
erst ausgeführt wird, nachdem(!) die andere ISR fertig ist.

Und dann stellt sich die Frage, ob Floating-Point Rechnereien in der ISR 
denn wirklich nötig sind.

Peter

von Andreas (Gast)


Lesenswert?

Daran hats gelegen, super Danke!

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.