Forum: Mikrocontroller und Digitale Elektronik C: LED-Fading; Licht flackert


von Johannes (menschenskind)


Lesenswert?

Hallo,

Es geht um eine eher simple Funktion: LED soll ein- und wieder ausfaden.
Zugriff auf die PWM-Werte 0..255 über ein Array mit 100 Elementen.
Das Einfaden hat funktioniert. Dann habe ich das Ausfaden noch 
integriert und den Code noch etwas optimiert aber nun hab ich das 
Problem, dass für "count"-Werte größer 49 die LED komisch flackert. Beim 
Ausfaden reagiert sie wieder normal sobald "count" kleiner 50 ist(das 
konnte ich nur durch eingrenzen der Werte in der letzten "if"-Anweisung 
herausfinden...)
Ich sitze jetzt hier bestimmt schon 1,5h dran, aber kriege das nicht 
gelöst.
Bitte helft mir.

Hannes

(Dieser Code ist Teil einer separaten c-Datei und wird aus der main 
)aufgerufen.
1
#include "includes/light_ws2812.h"
2
#include "includes/config.h"
3
#include <util/delay.h>
4
#include <math.h>
5
#include <stdlib.h>
6
7
#define PWM_MAX 255
8
#define RESOLUTION 50  //number of steps to increment the brightness value
9
10
11
struct cRGB COLORS[14];
12
struct cRGB LED_COLOR[1];
13
struct cRGB LED_COLOR_old[1]; //stores old color
14
struct cRGB LED_COLOR_new[1]; //stores new color
15
16
int16_t count = 0;
17
int16_t step = 1 ;
18
int16_t brightnesstable_index_red  = 0;
19
int16_t brightnesstable_index_green = 0;
20
int16_t brightnesstable_index_blue  = 0;
21
int16_t brightness_step_red    = 0;
22
int16_t brightness_step_green  = 0;
23
int16_t brightness_step_blue  = 0;
24
25
int16_t pwm_difference_red    = 0;
26
int16_t pwm_difference_green  = 0;
27
int16_t pwm_difference_blue    = 0;
28
29
uint8_t brightnesstable [100]={
30
0,0,0,0,0,1,1,1,1,2,
31
2,2,3,3,4,5,5,6,7,7,
32
8,9,10,11,12,13,14,15,17,18,
33
19,21,22,24,25,27,29,30,32,34,
34
36,38,40,42,44,46,48,51,53,55,
35
58,60,63,66,68,71,74,77,80,83,
36
86,89,92,96,99,102,106,109,113,116,
37
120,124,128,131,135,139,143,148,152,156,
38
160,165,169,174,178,183,188,192,197,202,
39
207,212,217,223,228,233,238,244,249,255
40
};
41
42
void initColors(void){
43
  COLORS[0].r=0;      COLORS[0].g=0;      COLORS[0].b=0; // black/dark
44
  COLORS[1].r=PWM_MAX;  COLORS[1].g=0;      COLORS[1].b=0; // red
45
  COLORS[2].r=PWM_MAX;  COLORS[2].g=1+PWM_MAX/2;  COLORS[2].b=0; // orange
46
  COLORS[3].r=PWM_MAX;  COLORS[3].g=PWM_MAX;  COLORS[3].b=0; // yellow
47
  COLORS[4].r=1+PWM_MAX/2;  COLORS[4].g=PWM_MAX;  COLORS[4].b=0; // green-yellow
48
  COLORS[5].r=0;      COLORS[5].g=PWM_MAX;  COLORS[5].b=0; // green
49
  COLORS[6].r=0;      COLORS[6].g=PWM_MAX;  COLORS[6].b=1+PWM_MAX/2; // mint-green
50
  COLORS[7].r=0;      COLORS[7].g=PWM_MAX;  COLORS[7].b=PWM_MAX; // turquois
51
  COLORS[8].r=0;      COLORS[8].g=1+PWM_MAX/2;  COLORS[8].b=PWM_MAX; // light blue
52
  COLORS[9].r=0;      COLORS[9].g=0;      COLORS[9].b=PWM_MAX; // blue
53
  COLORS[10].r=1+PWM_MAX/2;COLORS[10].g=0;  COLORS[10].b=PWM_MAX; // violet
54
  COLORS[11].r=PWM_MAX;  COLORS[11].g=0;      COLORS[11].b=PWM_MAX; // pink
55
  COLORS[12].r=PWM_MAX;  COLORS[12].g=0;      COLORS[12].b=1+PWM_MAX/2; // magenta
56
  COLORS[13].r=PWM_MAX;  COLORS[13].g=PWM_MAX;  COLORS[13].b=PWM_MAX; // white
57
}
58
59
struct cRGB colorPulse(uint8_t index){
60
  if(count == 0){
61
62
    pwm_difference_red    = pwmDifference(LED_COLOR_new[0].r,0); // Either 0, 127.5 or 255
63
    pwm_difference_green  = pwmDifference(LED_COLOR_new[0].g,0); // Either 0, 127.5 or 255
64
    pwm_difference_blue    = pwmDifference(LED_COLOR_new[0].b,0); // Either 0, 127.5 or 255
65
    
66
    brightness_step_red    = brighnessStep(pwm_difference_red); // Speed is 0 for same, 1/2 for 127 and 1 for 255 as difference each in positive or negative direction.
67
    brightness_step_green  = brighnessStep(pwm_difference_green); // Speed is 0 for same, 1/2 for 127 and 1 for 255 as difference each in positive or negative direction.
68
    brightness_step_blue  = brighnessStep(pwm_difference_blue); // Speed is 0 for same, 1/2 for 127 and 1 for 255 as difference each in positive or negative direction.
69
    
70
    LED_COLOR_new[0] = COLORS[index];
71
    LED_COLOR[0] = COLORS[0]; // switch off Color
72
  }
73
74
  brightnesstable_index_red  += step * brightness_step_red;
75
  brightnesstable_index_green += step * brightness_step_green;
76
  brightnesstable_index_blue  += step * brightness_step_blue;
77
  
78
  LED_COLOR[0].r = brightnesstable[brightnesstable_index_red];
79
  LED_COLOR[0].g = brightnesstable[brightnesstable_index_green];
80
  LED_COLOR[0].b = brightnesstable[brightnesstable_index_blue];
81
  
82
  count += step;
83
  
84
  if( (count == 100) || (count == 0) ){
85
    step = -step;
86
  }  
87
88
  return LED_COLOR[0];
89
}
90
91
int16_t pwmDifference(uint8_t pwm_Value_New, uint8_t pwm_Value_Old){
92
  return pwm_Value_New - pwm_Value_Old;
93
}
94
uint8_t brighnessStep (uint8_t pwm_Difference){
95
  return  ( (100*pwm_Difference) / PWM_MAX )/RESOLUTION;
96
}

von B. S. (bestucki)


Lesenswert?

Das sieht alles ein bisschen wirr aus. Du hast viele globale Variablen, 
was nicht gerade der Übersichtlichkeit zugute kommt, sogar solche, die 
von Funktionen zurückgegeben werden (z.B. LED_COLOR).

Johannes H. schrieb:
> struct cRGB LED_COLOR[1];

Es ist nicht nötig, diese Variable als Array anzulegen, die Grösse ist 
ja 1.

Johannes H. schrieb:
> LED_COLOR[0].r = brightnesstable[brightnesstable_index_red];
>   LED_COLOR[0].g = brightnesstable[brightnesstable_index_green];
>   LED_COLOR[0].b = brightnesstable[brightnesstable_index_blue];

Bist du sicher, dass die Indizes von brightnesstable alle kleiner als 
100 sind? Das wäre das erste, was ich in deinem Programm prüfen würde.

: Bearbeitet durch User
von Johannes (menschenskind)


Lesenswert?

Hallo Stucki,
Die ws2812_setleds (Die Funktion, die die Daten an die LED sendet) 
erwartet aber einen Pointer auf ein Array. Ich hatte es schon mal so 
gemacht, wie Du sagtest, da hatte ich aber mangels C-Kenntnissen 
Probleme, dass ich das falsch übergeben habe, deswegen lasse
ich das jetzt so mit dem LED_COLOR[1].

Aber ich glaube Dein Hinweis ist die Lösung, da ich diesen 
"brightness_index" für eine LED um 1 erhöhe und bei der anderen um 2. Da 
leuchtet ein, dass der nach 50 counts schon bei 100 ist.
Warum ich das nicht selbst gesehen habe...?

Und die Werte müssen global sein, erstens, da sie auch von anderen 
Funktionen verwendet werden und 2. weil die Werte bei jedem 
Funktionsaufruf sonst neu berechnet werden müssten.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> 2. weil die Werte bei jedem
> Funktionsaufruf sonst neu berechnet werden müssten.

Schau Dir mal an, was "static" Variablen innerhalb von Funktionen 
machen. Könnte in deinem Fall hilfreich sein.

von Johannes (menschenskind)


Lesenswert?

@Stefan:
Aber die Variablen werden ja auch noch in anderen Funktionen benutzt.

von B. S. (bestucki)


Lesenswert?

Johannes H. schrieb:
> Die ws2812_setleds (Die Funktion, die die Daten an die LED sendet)
> erwartet aber einen Pointer auf ein Array. Ich hatte es schon mal so
> gemacht, wie Du sagtest, da hatte ich aber mangels C-Kenntnissen
> Probleme, dass ich das falsch übergeben habe, deswegen lasse
> ich das jetzt so mit dem LED_COLOR[1].

Dann wirst du wahrscheinlich auch die Arraygrösse übergeben müssen? Dann 
könntest du auch einfach einen Zeiger auf eine Variable übergeben und 
die Grösse auf 1 setzen, macht keinen Unterschied.

Johannes H. schrieb:
> Und die Werte müssen global sein, erstens, da sie auch von anderen
> Funktionen verwendet werden und 2. weil die Werte bei jedem
> Funktionsaufruf sonst neu berechnet werden müssten.

Könnte man bestimmt anders machen, ausser die Werte werden in einem 
Interrupt benötigt. Bei globalen Variablen läuft man immer in die 
Gefahr, dass viele verstreute Funktionen darauf zugreifen und man im 
Fehlerfall nicht nachvollziehen kann, welche Funktion nun den falschen 
Wert geschrieben hat.

von Peter D. (peda)


Lesenswert?

Warum legst Du COLORS[14] nicht im Flash an, sondern umständlich zur 
Laufzeit?
Warum muß ein Index auf 100 Werte 16-bittig sein?
Wie wird gesichert, daß der Index innerhalb 0..99 liegt?

von TM (Gast)


Lesenswert?

Johannes H. schrieb:
> @Stefan:
> Aber die Variablen werden ja auch noch in anderen Funktionen benutzt.

Ja dann werden sie oder pointer auf diese Variablen im Funktionsaufruf 
mit übergeben. So ist das nur ein Haufen unübersichtlicher Mist. Sorry.

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.