C Lauflicht mit nach gedimmten LED´s

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Hallo,

Verständnis Frage ->



CodeBox C
for (LEDx = 0 ; LEDx < 14 ; LEDx++)
{
for ([I]uint8_t[/I] x = 0 ; x < 14 ; x++)
pwmChannel[x] = 0;

pwmChannel[LEDx -   0U] = 100;
pwmChannel[LEDx -   1U] = 30;
pwmChannel[LEDx -   2U] = 5;
pwmChannel[LEDx -   3U] = 2;
[B]//pwmChannel[LEDx - 4U] = 1[/B];

[I]_delay_ms[/I](SPEED);
}


Es sind alles unsigned Variablen...
Wenn ich jetzt die letzte Zeile in der for auskommentiere, läuft gar nichts mehr.
Abgesehen davon das es eigentlich sowieso nicht gehen darf (unsigned) wieso geht es nur bis


CodeBox C
pwmChannel[LEDx -   3U] = 2;


:eek:
 
Hi Janiiix,

so ganz verstehe ich deinen Code nicht.

LEDx ist doch sicherlich uint8_t. Als Array-Index verwendest du x und LEDx.
Bei kleineren LEDx Werten läuft der Index über, es könnte sogar sein, dass der Index 16 Bit überläuft, da du mit U (uinsigned int) arbeitest.

Nun müsste man genau wissen, wieviele PWM Kanäle du hast und wie du die PWM Werte verändern möchtest. Aus dem oberen Code kann ich mir das nicht so richtig vorstellen.
 
Es soll ein Lauflicht "KnightRider" werden. Mit dem Code Schnipsel, den ich oben gepostet habe, klappt das ja auch.
Nur wie du es auch schon gesagt hast, ist es undurchsichtig und es ist auch nicht wirklich toll, diese Lösung.
Die PWM´s stehen (Funktionieren auch!)

Jetzt fehlt halt nur die Routine um diesen Effekt dazustellen.



CodeBox C
typedef struct  
{
   uint8_t   Channel[14];
}pwm_t;

pwm_t volatile PWM;

uint8_t LEDx   = 0;
 
Sollte der Effekt nicht eher so sein, daß man quasi eine LED hin und herwandernd (sagen wir 2 Schritte pro Sekunde) voll an hat, und alle anderen LEDs dimmen je für sich selbst kontinuierlich runter?

Quick'nDirty zählt man Timerüberläufe, bei jedem davon werden alle PWM-Vorgabewerte dekrementiert bis sie Null sind, nur der aktive Kanal wird auf max gesetzt. Läuft der Überlaufszähler über, wandert der aktive Kanal eins weiter oder zurück.
 
Die lezten 3 angesteuerten sollten je eine unterschiedliche Helligkeit aufweisen.
 
Dann eben fünf (?) diskrete Werte von voll an bis ganz aus, irgendwo an aufeinanderfolgenden Adressen abgelegt. Jeder Kanal (LED) zeigt quasi auf eine der Adressen, bei jedem Schritt werden alle Kanäle (also die Werte darin) um eins erhöht (begrenzt auf die letzte "ganz aus"-Adresse), und der aktive Kanal weitergeschaltet, und auf die "ganz an" Adresse gesetzt.

@me findet wegfaden trotzdem besser:p
 
Wollte so wenig Speicherplatz in Anspruch nehmen wie geht. Lege ich jetzt ne Tabelle ab, habe ich ja automatisch wieder Speicherplatz in Anspruch genommen.
Mit rechnen, brauche ich zwar mehr Leistung, dass ist hier aber egal.
 
Hallo Janiiix,

ich hoffe ich habe dich richtig verstanden.

Du könntest es eventuell so lösen ...

pwm_set_channel verteilt pwm Werte um einen gewählten Index (0..13).
Der Array Wert des gewählten Index ist 100, die nächsten nebenan haben 30 danach 5 alle anderen 2.

Das kann man natürlich noch weiter ausbauen über Tabellen im Flash usw.

pwm_move_center ist nur zum Testen.



CodeBox C
uint8_t pwmChannel[14];

void pwm_move_center ( void );
void pwm_set_channel ( uint8_t center );

void pwm_move_center ( void )
{
   uint8_t i = 0;
 
   do
   {
       pwm_set_channel(i);
       i++;
       _delay_ms(100);
   } while (i<14);
 
   do
   {
       i--;
       pwm_set_channel(i);
       _delay_ms(100);
   } while (i>0);
 
 
}

// center = 0..13
void pwm_set_channel ( uint8_t center )
{
   uint8_t d;
 
   for (uint8_t u=0; u<14; u++)
   {
       if (center >= u)
          d = center-u;
       else
          d = u-center;
   
       if (d == 0)
          pwmChannel[u] = 100;
       else if (d == 1)
          pwmChannel[u] = 30;
       else if (d == 2)
          pwmChannel[u] = 5;
       else
          pwmChannel[u] = 2;
   
   }
 
}
 
Hm...
Das sieht ja schon mal recht gut aus. Nur es leuchten mehr als 3 LED´s (abgesehen von den anderen die in der Helligkeitsstufe 1 "inaktiv" sind)...

Eigentlich sollten ja nur -->


CodeBox C
       if (d == 0)
       PWM.Channel[u] = 250;
       else if (d == 1)
       PWM.Channel[u] = 15;
       else if (d == 2)
       PWM.Channel[u] = 5;
       else
       PWM.Channel[u] = 2;


4 Stk. heller leuchten als die anderen...

Es sollte eigentlich so aussehen -->

dunkel | weniger dunkel | hell

aus | dunkel | weniger dunkel | hell

aus | aus | dunkel | weniger dunkel | hell

usw...

Und die Anzahl der LED´s die leuchten sollen?
 
Zuletzt bearbeitet:
Bei meiner Version sollten rechts und links von der hellen LED die LEDs leuchten, immer geringer mit weiterem Abstand, minumal aber immer mit 2.
Bei dir bewegt sich die LED nur in eine Richtung und du möchtest so eine Art "Schweif"? Mir fehlt da ein bisschen Serienerfahrung ;)
 
Moin @Dirk ,
Wo ist denn deine Jugend hin? :p
Wie kommst du immer so schnell auf diese Lösungen, sich dort rein zu denken, ist manchmal echt nicht leicht.

Habe es inzwischen so gelöst.



CodeBox C
void pwm_move_center ( void )
{
    int8_t i = 0;
     
    do
    {
        pwm_set_channel(i,0);
        i++;
        _delay_ms(35);
    } while (i<14);
     
    do
    {
        i--;
        pwm_set_channel(i,1);
        _delay_ms(35);
    } while (i>0);
     
     
}

// center = 0..13
void pwm_set_channel ( uint8_t center,  uint8_t rotation )
{
    int8_t d;
     
    for (uint8_t u=0; u<14; u++)
    {
        if (rotation)
        d = (u)-(center);
        else
        d = (center) - (u);

        if      (d == 0)
        PWM.Channel[u] = 250;
        else if (d == 1)
        PWM.Channel[u] = 125;
        else if (d == 2)
        PWM.Channel[u] = 75;
        else if (d == 3)
        PWM.Channel[u] = 25;
        else
        PWM.Channel[u] = 1;
         
    }
     
}
 
Das sieht aus wie ein "Schweif".

Das könnte man ja vielleicht auch so lösen:

Eine Funktion setzt den maximalen Helligkeitswert für einen bestimmten Index.
Eine weitere Funktion (siehe unten) kümmert sich um Dimmen der anderen Helligkeitswerte ausserhalb des Index.

(So etwas ähnliches hatte ich mal bei einem FFT Spektrum mit Peek Hold Werten gemacht, die sich vom Maximum nach einer Wartezeit langsam wieder zum aktuellen Wert bewegt haben)



CodeBox C
// Aufruf zB alle 10ms, je nach PWM Auflösung
// Alles ausser aktueller Index wird gedimmt.
void pwm_autodim ( uint8_t index )
{
    
  for (uint8_t u=0; u<14; u++)
  {
    if ((u != index) && (PWM.Channel[u] > 0)) PWM.Channel[u]--;  
  } 
}
 
@Dirk
Das gleiche hat der letzte Quellcode von mir auch gemacht.
Sieht aber einfacher aus als vorher ;)
 
Zuletzt bearbeitet:
Das gleiche hat der letzte Quellcode von mir auch gemacht.
Sieht aber einfacher aus als vorher ;)

Also dein Code zuvor setzt konstante Werte in Abhängigkeit vom Abstand zum aktuellen Index..

Bei meinem Beispiel wäre es so, dass wenn man den Index plötzlich nicht mehr "bewegt" die Helligkeit von den anderen LEDs langsam auf Null geht.
Wie schnell man also runterdimmen muss, ist auch abhängig davon wie schnell man den Index "bewegt".
 
Eine Frage habe ich jedoch nicht, dass verstehe ich nicht...



CodeBox C
[I]uint8_t[/I] d = 0;

for ([I]uint8_t[/I] Index = 0; Index < 14; Index++)
{
if (Rotation) // Rotation = 1?

d = (Index) - (LedNum);
else // Rotation = 0?

/*

* LedNum = 0 - 13
* Index = 0 - 13
*
*/

d = (LedNum) - (Index); // 5 - 14 = - 9 -> uint8 ?

if (d == 0)
PWM.Channel[Index] = 250; // led 1

else if (d == 1)
PWM.Channel[Index] = 125; // led 2

else if (d == 2)
PWM.Channel[Index] = 75; // led 3

else if (d == 3)
PWM.Channel[Index] = 25; // led 4

else if (d == 4)
PWM.Channel[Index] = 10; // led 5

else

PWM.Channel[Index] = 2; // all other led´s

}


Wie kann das funktionieren, wenn ich einen uint Type habe?
Es klappt auf jeden fall...
 
Ich nehme an, es wird in int gerechnet und dann für d nach uint konvertiert.
 
Selbst wenn ich es caste?
 


CodeBox C
[I]uint8_t[/I] d = 0;

for ([I]uint8_t[/I] Index = 0; Index < 14; Index++)
{
/* calculate next index */


if (Rotation) // Rotation = 1 

d = ([I]uint8_t[/I])((Index) - (LedNum));
else // Rotation = 0 ?

d = ([I]uint8_t[/I])((LedNum) - (Index));
if (d == 0)
PWM.Channel[Index] = 250; // led 1

else if (d == 1)
PWM.Channel[Index] = 125; // led 2

else if (d == 2)
PWM.Channel[Index] = 75; // led 3

else if (d == 3)
PWM.Channel[Index] = 25; // led 4

else if (d == 4)
PWM.Channel[Index] = 10; // led 5

else

PWM.Channel[Index] = 0; // all other led´s

}


... Genau das selbe
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)