Forum: Mikrocontroller und Digitale Elektronik Fading in Schleife


von Tim S. (timer)


Lesenswert?

Hi,

ich habe folgendes Problem. Ziel ist es, eine LED-Fading zu realisieren. 
Klar habe ich die Artikel dazu gelesen. Mein Code führt dazu das die LED 
ehr unkoordiniert flackert.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
#include <stdbool.h>
5
6
#define LED_DDR (DDRD)
7
#define LED_PORT (PORTD)
8
#define LED (1<<3)
9
10
static const uint16_t pwmtable_16[256] PROGMEM =
11
{
12
  0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
13
  3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7,
14
  7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15,
15
  15, 16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
16
  31, 32, 33, 35, 36, 38, 40, 41, 43, 45, 47, 49, 52, 54, 56, 59,
17
  61, 64, 67, 70, 73, 76, 79, 83, 87, 91, 95, 99, 103, 108, 112,
18
  117, 123, 128, 134, 140, 146, 152, 159, 166, 173, 181, 189, 197,
19
  206, 215, 225, 235, 245, 256, 267, 279, 292, 304, 318, 332, 347,
20
  362, 378, 395, 412, 431, 450, 470, 490, 512, 535, 558, 583, 609,
21
  636, 664, 693, 724, 756, 790, 825, 861, 899, 939, 981, 1024, 1069,
22
  1117, 1166, 1218, 1272, 1328, 1387, 1448, 1512, 1579, 1649, 1722,
23
  1798, 1878, 1961, 2048, 2139, 2233, 2332, 2435, 2543, 2656, 2773,
24
  2896, 3025, 3158, 3298, 3444, 3597, 3756, 3922, 4096, 4277, 4467,
25
  4664, 4871, 5087, 5312, 5547, 5793, 6049, 6317, 6596, 6889, 7194,
26
  7512, 7845, 8192, 8555, 8933, 9329, 9742, 10173, 10624, 11094,
27
  11585, 12098, 12634, 13193, 13777, 14387, 15024, 15689, 16384,
28
  17109, 17867, 18658, 19484, 20346, 21247, 22188, 23170, 24196,
29
  25267, 26386, 27554, 28774, 30048, 31378, 32768, 34218, 35733,
30
  37315, 38967, 40693, 42494, 44376, 46340, 48392, 50534, 52772,
31
  55108, 57548, 60096, 62757, 65535
32
};
33
34
35
void setup()
36
{
37
  //Port
38
  LED_DDR |= LED;
39
  LED_PORT |= LED;
40
  //Timer
41
  TIMSK1 = ((1<<OCIE1A) | (1<<TOIE1));
42
  TCCR1B |= (1<<CS10);
43
  //Interrupt
44
  sei();
45
}
46
47
void loop(void)
48
{
49
  static uint8_t u8I = 0;
50
  OCR1A = pwmtable_16[u8I++];
51
  delay(400);
52
}
53
54
ISR(TIMER1_COMPA_vect)
55
{
56
  LED_PORT |= LED; // switch led off
57
}
58
59
ISR(TIMER1_OVF_vect)
60
{
61
  LED_PORT &= ~LED; // switch led on
62
}

Ich habe es auch mit for-Schleife in der loop-Funktion probiert, was 
ebenso nicht funktioniert. Was allerdings funktioniert, wenn ich das 
Fading manuell mache, also wie folgend.
1
void loop(void)
2
{
3
  uint16_t u16Delay = 400;
4
  
5
  OCR1A = pwmtable_16[1];
6
  delay(u16Delay);
7
  OCR1A = pwmtable_16[2];
8
  delay(u16Delay);
9
  OCR1A = pwmtable_16[3];
10
  delay(u16Delay);
11
  OCR1A = pwmtable_16[4];
12
13
// Und so weiter
14
}

Für mich ist das Verhalten rätselhaft. Als wenn die loop nicht korrekt 
Kompiliert wird.

von Falk B. (falk)


Lesenswert?

@Tim S. (timer)

>ich habe folgendes Problem. Ziel ist es, eine LED-Fading zu realisieren.
>Klar habe ich die Artikel dazu gelesen. Mein Code führt dazu das die LED
>ehr unkoordiniert flackert.

Hmm. Was hindert dich daran, einfach mal de  Originalquelltext 
unverändert auf deinen AVR zu laden? Das minimiert die Fehlerquellen.


>  TIMSK1 = ((1<<OCIE1A) | (1<<TOIE1));
>  TCCR1B |= (1<<CS10);

Wo wird OCRx freigeschaltet? COMxy Bits.

>ISR(TIMER1_COMPA_vect)
>{
>  LED_PORT |= LED; // switch led off
>}

Das LED-Fading im Artikel benutzt die Hardware-PWM, was vor allem bei 16 
Bit PWM auch gar nicht ander geht. Du versuchst hier ein Software-PWM.


>Ich habe es auch mit for-Schleife in der loop-Funktion probiert, was
>ebenso nicht funktioniert. Was allerdings funktioniert, wenn ich das
>Fading manuell mache, also wie folgend.

Glaub ich nicht so recht, das ist eher ein Dreckeffekt, der dir ein 
funktionierendes Programm vorgaukelt.

>Für mich ist das Verhalten rätselhaft. Als wenn die loop nicht korrekt
>Kompiliert wird.

;-)

von Tim S. (timer)


Lesenswert?

Falk B. schrieb:
>
> Hmm. Was hindert dich daran, einfach mal de  Originalquelltext
> unverändert auf deinen AVR zu laden? Das minimiert die Fehlerquellen.


Weil ich Soft-PWM benötige, der Fading-Artikel verwendet Hardware-PWM. 
Der Code aus dem Soft-PWM Artikel realisiert PWM auf nen ganzen Port, 
ich brauche ihn für einen speziellen Pin.


> Wo wird OCRx freigeschaltet? COMxy Bits.

Wegen Soft-PWM brauche ich die Pins nicht.


> Das LED-Fading im Artikel benutzt die Hardware-PWM, was vor allem bei 16
> Bit PWM auch gar nicht ander geht. Du versuchst hier ein Software-PWM.

Ja, das versuche ich.

> Glaub ich nicht so recht, das ist eher ein Dreckeffekt, der dir ein
> funktionierendes Programm vorgaukelt.

Dreckeffekt? Warum sollte es nicht funktionieren?

von Falk B. (falk)


Lesenswert?

@ Tim S. (timer)

>Weil ich Soft-PWM benötige, der Fading-Artikel verwendet Hardware-PWM.
>Der Code aus dem Soft-PWM Artikel realisiert PWM auf nen ganzen Port,
>ich brauche ihn für einen speziellen Pin.

Leg lieber einen Draht auf deiner Platine zum passenden PWM-Pin, das 
geht deutlich schneller und ist einfacher.

>> Das LED-Fading im Artikel benutzt die Hardware-PWM, was vor allem bei 16
>> Bit PWM auch gar nicht ander geht. Du versuchst hier ein Software-PWM.

>Ja, das versuche ich.

Hast du schon mal einen Gedanken daran verschwendet, warm man in 
bestimmten Situationen KEIN Software-PWM verwenden will/kann. Und wo die 
Grenzen von Soft-PWM liegen?

: Bearbeitet durch User
von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi
1
void loop(void)
2
{
3
  static uint8_t u8I = 0;
4
  OCR1A = pwmtable_16[u8I++];
5
  delay(400);
6
}

Wenn ich den Code richtig verstehe, wird die Variabel u8I auf 0 gesetzt 
und danach der Wert 1 (u8I + 1, oder Wert 0 und u8I um Eins erhöht) des 
Array in das Match-A-Register des Timer 1 geladen.
Und Das immer wieder - da ich das '=0' so interpretiere, daß der 
Variabel JEDES MAL der Wert 0 zugeteilt wird.

Wenn NICHT, also diese Zuweisung nur 1x ausgeführt wird - gehört die 
Zeile eher in den Init-Bereich.

MfG

von Tim S. (timer)


Lesenswert?

Falk B. schrieb:
> Leg lieber einen Draht auf deiner Platine zum passenden PWM-Pin, das
> geht deutlich schneller und ist einfacher.

Die sind alle schon belegt.

> Hast du schon mal einen Gedanken daran verschwendet, warm man in
> bestimmten Situationen KEIN Software-PWM verwenden will/kann. Und wo die
> Grenzen von Soft-PWM liegen?

Verschwendet ist hier vielleicht der richtige Ausdruck. Eine LED zu 
dimmen sollte wohl kein Problem darstellen. Zu mal es ja bei manueller 
Programmierung funktioniert.

von Tim S. (timer)


Lesenswert?

Patrick J. schrieb:
> Wenn ich den Code richtig verstehe, wird die Variabel u8I auf 0 gesetzt
> und danach der Wert 1 (u8I + 1, oder Wert 0 und u8I um Eins erhöht) des
> Array in das Match-A-Register des Timer 1 geladen.
> Und Das immer wieder - da ich das '=0' so interpretiere, daß der
> Variabel JEDES MAL der Wert 0 zugeteilt wird.
>
> Wenn NICHT, also diese Zuweisung nur 1x ausgeführt wird - gehört die
> Zeile eher in den Init-Bereich.
>
> MfG

Die Variable ist statisch, dass heißt, sie wird nur einmalig 
initialisiert. Ich kann sie natürlich auch global deklarieren und dann 
im setup-Bereich initialisieren. Kommt aber auf's gleiche heraus.

von Falk B. (falk)


Lesenswert?

@ Tim S. (timer)

>Verschwendet ist hier vielleicht der richtige Ausdruck. Eine LED zu
>dimmen sollte wohl kein Problem darstellen. Zu mal es ja bei manueller
>Programmierung funktioniert.

Schon mal nachgerechnet, wie oft deine beiden ISRs aufgerufen werden?

von Rolf M. (rmagnus)


Lesenswert?

Patrick J. schrieb:
> Wenn NICHT, also diese Zuweisung nur 1x ausgeführt wird - gehört die
> Zeile eher in den Init-Bereich.

Das ist keine Zuweisung, sondern eine Initialisierung. Und da die 
Variable static ist, wird sie nur einmal erzeugt und damit auch nur 
einmal initialisiert.

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.