www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Soft-PWM macht nicht was es soll


Autor: Marcel Holle (multiholle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bekomme mein Software PWM für mehrere Kanäle nicht zum Laufen. Jetzt 
habe ich mich erstmal auf einen Kanal beschränkt, jedoch klappt das 
immer noch nicht.

Die LED habe ich auf den Wert 2 von 255 gesetzt. Sie leuchtet jedoch 
nicht schwach sondern blinkt sichtbar sehr schnell. Beim Code habe ich 
mich an dem Soft-PWM-Tutorial von hier orientiert.

Was mache ich falsch?


Hier mein Code:
#define F_PWM     100
#define CHANNELS  1
#define STEPS     256
#define PRESCALER 1
#define T_PWM     (F_CPU / PRESCALER * F_PWM * STEPS)

volatile uint8_t sync;
uint16_t timings_A[CHANNELS + 1];
uint16_t timings_B[CHANNELS + 1];

uint8_t steps = 1;
uint8_t buf_steps;
uint16_t* timings = timings_A;
uint16_t* buf_timings = timings_B;

ISR(TIMER1_COMPA_vect) {
  static uint8_t step;

  // switch led
  if (step == 0) {
    PORTC |= (1 << PC4);
    OCR1A = timings[0];
  } else {
    PORTC &= ~(1 << PC4);
    OCR1A += timings[step];
  }
  
  // set next step
  step++;
  if (step == steps) {
    step = 0; 
     
    // swap
    if (sync) {
      uint8_t tmp_steps = steps;
      steps = buf_steps;
      buf_steps = tmp_steps;

      uint16_t* tmp_timings = timings;
      timings = buf_timings;
      buf_timings = tmp_timings;

      // set swap finish
      sync = 0;
    }
  }
}

void set(uint8_t value) {
  // set pwm values
  buf_timings[0] = T_PWM * value;
  buf_timings[1] = T_PWM * (255 - value); 

  buf_steps = 2;

  // wait for sync
  sync = 1;

  // wait for swap finish
  while (sync == 1);
}

int main(void) {
  // set timer prescaler to F_CPU/8
    TCCR1B |= (1 << CS11);
  // enable output compare interrupt
    TIMSK1 |= (1 << OCIE1A);
  // enable global interrupts
  sei();

  // set led output
  DDRC |= (1 << PC4);

  // test
  set(2);


  while (1);
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel Holle schrieb:

> Was mache ich falsch?

Warum hast du deinen Compiler angelogen?


> #define PRESCALER 1

> int main(void) {
>   // set timer prescaler to F_CPU/8
>     TCCR1B |= (1 << CS11);


Die Berechnung auf 100Hz (T_PWM) basiert auf einem Prescaler von 1, den 
Timer stellst du aber auf einen Prescaler von 8. D.h. die Berechnung der 
Compare Werte ergibt Werte die 8 mal zu groß sind. Damit kriegst du 
nicht 100Hz PWM-Wiederholfrequenz sondern nur 12.5Hz. Und das siehst du 
dann.

Autor: Marcel Holle (multiholle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, das Flimmern ist jetzt weg. Allerdings leuchtet die LED konstant mit 
einer Helligkeit, egal welche Einstellung ich setze (2 oder 240 ist kein 
Unterschied).

Ich berechne die Zeiten im Array timings und übergebe sie dann im 
jeweiligen PWM-Schritt an den Timer. Was mache ich falsch?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel Holle schrieb:

> Ich berechne die Zeiten im Array timings und übergebe sie dann im
> jeweiligen PWM-Schritt an den Timer. Was mache ich falsch?

Mit welcher Taktfequenz betreibst du den Controller? Welchen Prescaler?
Hast du schon mal nachgerechnet, was bei T_PWM für Werte rauskommen?
Wenn die zu klein sind, dann kommt deine ISR nicht mehr hinterher, bzw. 
es bleibt kaum noch Rechenzeit für etwas anders als Compare Matches 
übrig.

Noch ein Detail am Rande:
Denk nochmal über die Reihenfolge der Initialisierungen im main() nach. 
Es ist wohl kaum sinnvoll zuerst durch eine Tür zu gehen und sie erst 
dann zu öffnen. Genauso ist es bei Initialisierungen (auch wenn das 
jetzt bei dir kein Problem darstellt)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Marcel Holle (multiholle)

>nicht schwach sondern blinkt sichtbar sehr schnell. Beim Code habe ich
>mich an dem Soft-PWM-Tutorial von hier orientiert.

Ohje. Und warum zerpflückst du einen super funktionierendes Programm und 
machst so einen Murks?

Autor: Marcel Holle (multiholle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
T_PWM hat den Wert 97, ist das zu gering?

Falk Brunner schrieb:
> Ohje. Und warum zerpflückst du einen super funktionierendes Programm und
> machst so einen Murks?
Ich kopiere nicht gerne einfach nur den Code. Ich möchte ihn verstehen, 
sonst bringt er mir nichts :/ Aber so richtig komme ich nicht klar.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel Holle schrieb:
> T_PWM hat den Wert 97, ist das zu gering?

Sollte reichen.
F_CPU ?
Prescaler ?

> Falk Brunner schrieb:
>> Ohje. Und warum zerpflückst du einen super funktionierendes Programm und
>> machst so einen Murks?
> Ich kopiere nicht gerne einfach nur den Code. Ich möchte ihn verstehen,
> sonst bringt er mir nichts :/ Aber so richtig komme ich nicht klar.

Wenn man Code verstehen will, denn man übernimmt, gibt es eine einfache 
Reihenfolge:

Zuerst wird der Code so wie er ist übernommen und getestet. Tut er das 
was der Autor behauptet?

Wenn nein, dann den Autor kontaktieren

Wenn ja, dann gehts weiter. Dann macht man erste kleine Veränderungen. 
Zwischendurch immer wieder kontrollieren: tut er noch?

Weitere Veränderungen. Dazwischen immer wieder: Tut er noch?

Und wenn man dann an einem Ende angelangt ist, dann stellt man sich die 
Frage: Jetzt nachdem ich alle Details verstehe - schreibe ich ihn neu 
oder nicht?

Wenn man viel Erfahrung hat, dann macht man manchmal auch dieses:
Man studiert den Code in allen Details und schreibt ihn neu. Allerdings 
muss man da meistens schon viel Erfahrung haben und auch darin geübt 
sein, Nebeneffekte im Code zu sehen.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger (kbuchegg) (Moderator)

Genau so siehts aus!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.