Led PWM Fade

Moin,

ich würde gerne eine Schaltung aufbauen, die wie folgt aussieht:

Mit einem kurzen Tastdruck soll eine Led langsam über PWM angehen, eine gewisse Zeit anbleiben und denn langsam ausgehen - oder über einen anderen Taster sofort langsam wieder ausgehen .

Kann mir jemand mit dem Sketch helfen ?

Danke im voraus !!! :slight_smile:

Du hast doch hier PWM Led Fade IN / Fade OUT - #3 by Plink - Deutsch - Arduino Forum schon eine Antwort bekommen.
Was gefällt dir daran nicht ?

Ja da bin ich auch sehr dankbar für ;D

aber ich würde dies gerne erweitern und ich muss mich erstmal in diese PWM Geschichte reinlesen.
Da dachte ich mir ein bissel unterstützung kann nicht schaden.

Plink:
aber ich würde dies gerne erweitern und ich muss mich erstmal in diese PWM Geschichte reinlesen.

Das solltest du auch machen.

Wenn du dann deinen Sketch zeigst, werden wir dir sicher weiter helfen.
Aber ohne deine Mithilfe wird das schwer.

Sieh dir die Grundlagen in der IDE an und über ein wenig.
Dann wirst du sicher weiter kommen.

Wir haben all so angefangen und selbst an den zahlreichen Beispielen gelernt.

und ich muss mich erstmal in diese PWM Geschichte reinlesen.

Wie kann ich dich dabei unterstützen?

combie:
Wie kann ich dich dabei unterstützen?

Könnte ich dieses Sketch dafür nutzen?
Ich bekomme es nicht hin, die Led zu dimmen, wenn ich den Taster kurz drücke.
Sie soll halt durch kurzen Tastendruck langsam aufleuchten und denn nach einiger Zeit langsam ausdimmen.

int ledPin = 9;
int buttonPin = 7;
boolean currentState = LOW;
boolean lastState = LOW;
boolean ledState = LOW;

void setup(){
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}

void loop(){
currentState = digitalRead(buttonPin);
if (currentState == HIGH && lastState == LOW){
Serial.println("pressed");
delay(1);
if (ledState == HIGH){
digitalWrite(ledPin, LOW);
ledState = LOW;
} else {
digitalWrite(ledPin, HIGH);
ledState = HIGH;
}
}

lastState = currentState;
}

Was stellst du dir denn unter "dimmen" vor?
Ich sehe da keinen Versuch des "dimmens".

Vielleicht sollten wir und erstmal auf ein gemeinsames Vokabular einigen...

Plink:
Moin,

ich würde gerne eine Schaltung aufbauen, die wie folgt aussieht:

Mit einem kurzen Tastdruck soll eine Led langsam über PWM angehen, eine gewisse Zeit anbleiben und denn langsam ausgehen - oder über einen anderen Taster sofort langsam wieder ausgehen .

Kann mir jemand mit dem Sketch helfen ?
Danke im voraus !!! :slight_smile:

Im englischsprachigen Teil des Forums habe ich gerade etwas ähnliches gepostet, und zwar als Antwort darauf, wie man mit Arduino eine "Finite State Machine" (FSM), zu deutsch "endlicher Zustandsautomat" realisieren kann.

Daraufhin habe ich ein Beispielprogramm für vier Zustände gemacht und gepostet, die vier Zustände sind:

  • LEDOFF
  • FADEUP
  • LEDON
  • FADEDOWN
  • und dann alles wieder von vorne, eine Zeitsteuerung ohne Button. Aber wäre leicht auf Buttonsteuerung umzubauen.

Soll ich das Beispielprogramm mal mit Deinen Pin-Vorgaben

int ledPin = 9;
int buttonPin = 7;
auf Buttonsteuerung umschreiben und dann hier posten?

Vielleicht fällt Dir ja noch ein, was Du mit "langsam" in Deiner Beschreibung "langsam angehen" und "langsam ausgehen" meinst? Kann man den Zeitraum in Sekunden ausdrücken? Oder in Minuten?

jurs:
Soll ich das Beispielprogramm mal mit Deinen Pin-Vorgaben

int ledPin = 9;
int buttonPin = 7;
auf Buttonsteuerung umschreiben und dann hier posten?

Vielleicht fällt Dir ja noch ein, was Du mit "langsam" in Deiner Beschreibung "langsam angehen" und "langsam ausgehen" meinst? Kann man den Zeitraum in Sekunden ausdrücken? Oder in Minuten?

Das wäre sehr nett!
also mit "langsam" meine ich wie "Fade In" oder "Fade Out" über PWM

combie:
Was stellst du dir denn unter "dimmen" vor?

Ich kenne leider nicht so das Fachvokabular, ich meine das eine LED in einem gewissen Zeitraum von 0 auf 255 dimmt.

Mein Versuch sieht so aus, aber irgendwie klappt das vorne und hinten nicht....

bool _ABVAR_1_1= false ;
int brightness = 0;
void Unterprogramm();
int led = 9;

void setup()
{
pinMode( 2 , INPUT);
pinMode( 3 , INPUT);
pinMode(led, OUTPUT);
_ABVAR_1_1 = LOW ;

}
void loop()
{
if ( digitalRead( 2))
{
_ABVAR_1_1 = HIGH ;
Unterprogramm();
delay( 4000 );
_ABVAR_1_1 = LOW ;
Unterprogramm();
}
}
void Unterprogramm()
{
analogWrite(led, brightness);
if (_ABVAR_1_1)
{
(brightness = brightness + 1 ) ;
}
else
{
brightness = brightness - 1 ;
}
if (brightness > 255) brightness = 255;
if (brightness < 0) brightness = 0;

delay(5);
}

Plink:
Das wäre sehr nett!
also mit "langsam" meine ich wie "Fade In" oder "Fade Out" über PWM

Ein Fadevorgang dauert dann wieviele Sekunden? Oder wieviele Minuten? Was ist "langsam"?

Und soll das Faden mit linearem Duty-Cycle erfolgen?
Also in 10% der Gesamtzeit beim Hochfaden den Duty-Cycle von 0% auf 10% steigern und entsprechend beim Runterfaden in 10% der Gesamtzeit den Duty-Cycle von 100% auf 90% herunterregeln?

Oder soll es nach dem Helligkeitsempfinden erfolgen, so dass gleiche Zeitabstände gleichen Helligkeitsunterschieden entsprechen?

Denn beim linearen Faden tritt wegen der logarithmischen Helligkeitswahrnehmung folgender Effekt auf: In den unteren PWM-Stufen treten Sprünge auf, d.h. PWM(2) ist doppelt so hell wie PWM(1). Aber am oberen Ende ändert sich fast nichts mehr und PWM(253) und PWM(254) und PWM(155) lassen sich per Auge in der Helligkeit überhaupt nicht unterscheiden. So dass beim linearen Faden der Effekt auftritt: Beim Hochfaden steigert sich die Helligkeit zuerst sehr schnell, am Ende des Hochfadens dann fast überhaupt nicht mehr. Und beim Runterfaden ist es umgekehrt, also zuerst passiert fast nichts, und erst am Ende des Fadevorgangs sinkt die Helligkeit dann plötzlich sehr rasch.

Eine über die Zeit gleichmäßige Hellitkeitsänderung darf also den Duty-Cycle der PWM nicht linear ändern, sondern muß im unteren Helligkeitsbereich lin kleineren Schritten als im oberen Helligkeitsbereich erfolgen.

Das wäre sehr nett!

Ich schaue dann mal, dass ich in meine State-Machine-Demo eine Buttonsteuerung einbaue.
Bevor ich mir dann über die Optimierung des Fadevorgangs Gedanken mache.

Ich melde mich dann wieder. Aber ich muss heute zwischendurch noch bei mir zuhause zwei Bahnen Tapete kleben.

Das Probelm ist, dass vorgekauter Code hier vermutlich nicht dem "Plink" auf die Sprünge hilft...

Beim Fische essen, lernt man nicht das selber angeln.

#include <TaskMacro.h>
// https://forum.arduino.cc/index.php?topic=415229.0

const byte taster = 7; // interner Pullup, Taster schaltet gegen GND
const byte LED    = 9; // led mit Vorwiderstand gegen GND
const byte stufen[16] =
{
    0, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 90, 128, 181, 255
};

void TuDimDing(void)
{
  static int i; // schleifenzähler
  taskBegin();
  while(1)
  {
     taskWaitFor(!digitalRead(taster));  // auf Tastendruck warten

     // aufdimmen
     for(i=0;i < sizeof(stufen);i++)
     {
      Serial.println(stufen[i]);
      analogWrite(LED,stufen[i]);
      taskPause(100); 
     } 
     taskWaitFor(!digitalRead(taster)); // auf Tastendruck warten

     // abdimmen
     for(i=sizeof(stufen)-1;i >= 0;i--)
     {
      Serial.println(stufen[i]);
      analogWrite(LED,stufen[i]);
      taskPause(100); 
     } 
  }

  
  taskEnd();  
}


void setup() 
{
    pinMode(taster,INPUT_PULLUP);
    Serial.begin(9600);
}

void loop() 
{
  TuDimDing();
}

OK, Tapetenkleister wird ja nicht so schnell hart wie Gips, also können die beiden Tapetenbahnen noch warten.

Hier erstmal der FSM Code für eine Finite State Machine mit vier Zuständen:

#define runEvery(t) for (static uint16_t _lasttime;\
                         (uint16_t)((uint16_t)millis() - _lasttime) >= (t);\
                         _lasttime += (t))

const byte ledPin=13;
const byte buttonPin=7;
byte currentState;
unsigned long stateActiveSince;

void softPWM(byte fadeVal)
{
 digitalWrite(ledPin,HIGH);
 delayMicroseconds(fadeVal*10);
 digitalWrite(ledPin,LOW);
 delayMicroseconds((255-fadeVal)*10);
// Serial.println(fadeVal);
}


enum states {LEDOFF, FADEUP, LEDON, FADEDOWN};

void setState(byte index)
{
  currentState=index;
  stateActiveSince=millis();
  Serial.print("Current state is: ");Serial.println(index);
}


long stateTime()
//returns number of milliseconds since current state was set
{
  return millis()-stateActiveSince;
}


typedef void (* stateFuncPtr)(); // declare the prototype of a state function pointer

bool buttonPressed()
{
  bool result=false;
  static byte oldButtonState;
  byte buttonState=digitalRead(buttonPin);
  if(buttonState!=oldButtonState&&buttonState==LOW) result=true;
  oldButtonState=buttonState;
  return result;
}


void funcLedOff() 
{
  runEvery(3) if(buttonPressed()) setState(FADEUP);
digitalWrite(ledPin,LOW);  
}
void funcFadeUp() 
{
  byte fadeVal=0;
  if (stateTime()>5100) setState(LEDON);
  else{ fadeVal=stateTime()/20; softPWM(fadeVal);}
 return; 
}

void funcLedOn()
  {
  if (stateTime()>10000) setState(FADEDOWN);
digitalWrite(ledPin,HIGH);  
    
  }
void funcFadeDown() 
{
  byte fadeVal=255;
  if (stateTime()>5100) setState(LEDOFF);
  else {fadeVal=255-stateTime()/20; softPWM(fadeVal);}
  return;
}

stateFuncPtr stateFunctions[]= {&funcLedOff,&funcFadeUp,&funcLedOn,&funcFadeDown};                         
// *currentFunction=funcLedOff; 

                       






void setup()
{
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  pinMode(buttonPin,INPUT_PULLUP);
  setState(LEDOFF);
}


void loop()
{
  stateFunctions[currentState]();
}

Die vier Zustände sind LEDOFF,FADEUP, LEDON und FADEDOWN, und werden immer in dieser Reihenfolge durchgesteuert:

Anfangszustand LEDOFF
-bei Tastendruck== FADEUP(linear, innerhalb 5.1 Sekunden)
-nach dem Hochfaden automatische Umschaltung in LEDON

  • dann nach 10 Sekunden automatische Umschaltung in FADEDOWN (linear, innerhalb 5.1 Sekunden)

-nach dem Runterfaden automatische Umschaltung in LEDOFF
Und dann kann per Tastendruck wieder in FADEUP umgeschaltet werden.

Probier's mal aus!

Der Taster muss wie folgt angeschlossen sein: Ein Pol an GND, der andere an den im Code definierten Arduino-Pin (es wird der interne Pull-Up Widerstand verwendet und per INPUT_PULLUP aktiviert).

Die LED kann übrigens an einen beliebigen Pin angeschlossen werden, es muss kein PWM-Pin sein, denn die analogWrite Funktion findet in diesem Beispiel keine Verwendung, sondern es wird eine kleine SoftwarePWM Funktion realisiert, die eine LED an jedem beliebigen Pin faden kann.

Probier's mal aus!
Was meinst Du?

Verstehst Du von dem State-Machine-Code etwas?