Tasterprogramm

Hallo Leute!

Ich habe wieder einmal eine Frage! Und zwar möchte ich eine LED hoch und runterdimmen mit 2 Tastern. Beim Hochdimmen gibt es keine Probleme. Nur beim runterdimmen springt der Wert der Led wenn sie aus ist wieder nach oben. Ein weiteres Problem ist, wenn die Led hochgedimmt ist und der Taster erneut betätigt wird dimmt die led vom Neuem.
Wie kann man das verhindern!

Der bisherige Code sieht daweil so aus. Bin für jede Hilfe dankbar!
Euer Hermann_88

int ledpin = 9;
int Taster1 = 2;
int Taster2 = 4;

int value1 = 0;
int value2 = 0;


void setup (){
  
  Serial.begin(9600);
  pinMode(ledpin,OUTPUT);
  pinMode(Taster1,INPUT);
  pinMode(Taster2,INPUT);
}
void loop (){
  value1 = digitalRead(Taster1);
  value2 = digitalRead(Taster2);
  
  if(value1 == HIGH) {
    for (value1 <=255 ; value1 +=2;){
    analogWrite(ledpin, value1);
    delay(50);
    if (value1 == 255){
  break;
      }
      
    }
  } 
  
  if(value2 == HIGH) {
    
    for (value2 >= 255; value2 -=2;){
    analogWrite(ledpin, value2);
    delay(50);
     if (value2 == 0){
    break;
      }
  }
  }
}

EDIT BY MOD: added code tags
MOVED INTO PROPER LANGUAGE SECTION

  1. HIGH ist 1. Nicht 255. Du solltest da nicht mit dem Rückgabe-Wert von digitalRead() arbeiten, sondern die Schleifen-Variable per Hand auf ihren Ausgangswert setzen.

  2. Selbst wenn du von 255 immer wieder 2 abziehst, kommst du nicht genau auf 0, da die Zahl ungerade ist. Du solltest die Abfrage auf > 255 oder < 0 machen. Nicht auf einen bestimmten Wert.

  3. Die for-Schleife ist hier sowieso Fehl am Platz. Einfach wenn der Taster gedrückt wurde einmal inkrementieren, bzw. dekrementieren.

Meine Taster gehen gegen GND
Interne Pullup aktiviert

const int ledpin = 9;
const int Up     = 2;
const int Down   = 4;
const unsigned long speed   = 10; // kleinere Zahl schnelleres dimmen


struct Automat
{
  int dim = 0;
  unsigned long lastHit;
  Automat()
  {
    lastHit = millis();
    analogWrite(ledpin,dim);
  }
  
  void handle() 
  {
    if(millis() - lastHit >= speed)
    {
      lastHit = millis();
      int neuerdim = dim; 
      if(!digitalRead(Up)) neuerdim++;
      if(!digitalRead(Down)) neuerdim--;
      neuerdim = constrain(neuerdim,0,255);
      if(neuerdim != dim)
      {
        dim = neuerdim;
        analogWrite(ledpin,dim);
      }
    }  
  }
} Dimmer;

void setup ()
{
  pinMode(Up,INPUT_PULLUP);
  pinMode(Down,INPUT_PULLUP);
}
void loop ()
{
  Dimmer.handle();
}

Hallo Combie!

Das Programm ist wirklich toll. Ein einziges Problem dabei ist, dass die LED auch bei einem ganz kurzen HighSignal ganz hochdimmen soll. In dem Programm muss man den Taster dafür gedrückt halten. Würde das noch irgendwie gehn, die Funktion einzubauen?

LG

Klar kann man das!

Dann müsste man in der handle Methode einen einfachen endlichen Automaten einbauen.

Hi

Haha ist einmal nicht schlecht, dass es funktionieren würde. Nur ich bin ein totaler Anfänger und check das mit den Automaten nicht ganz. Es wäre echt lieb wenn du mir wenn du willst, das ein wenig erklären könntest. Welche Zeile im Programm, was macht.
Ich wäre dir echt dankbar dafür :grin:

LG Hermann

Welche Zeile im Programm, was macht.

Was verstehst du denn nicht?

wie man so einen automaten strukturiert und was das mit dem millis() auf sich hat

Millis?
Dimmen hat was mit Zeit zu tun.
Du verwendest delay() dafür.
Dein Programm blockiert an den Stellen.

Zum endliche Automaten oder FSM gibts hier einige Threads
z.B. dieser hier: LED Dimmen - #9 by combie - Deutsch - Arduino Forum

Ok, aber wie kann ich dem sagen, dass er nur auf den Tastendruck der 2 Taster hören soll?

Ich habs geschafft. Danke für deine Hilfe! :smiley:

Ok ja ein Problem ist jetzt doch noch aufgetreten. Und zwar kann beim ersten aktivieren, die LED nicht hochdimmen. Es muss zuerst der runterdimmtaster betätigt werden. Dann funktioniert alles einwandfrei.

const unsigned int dimpin     = 3; // pin -- R -- LED -- GROUND
const unsigned int tasterpin1  = 4 ; // Pin -- Taster -- GROUND
const unsigned int tasterpin2  = 2 ; // Pin -- Taster -- GROUND
const unsigned int dimSpeed   = 50; // mS pro dimschritt



enum  AutomatenStatus {A_Taster1, A_Taster2, A_DimUp, A_DimDown};

struct Automat {
 AutomatenStatus status;
 unsigned long lastHit;
 byte dim;
 Automat() // Konstruktor
 {
   lastHit = millis();
   dim     = 0;
   status = A_Taster1;
   status = A_Taster2;
 }
} Astatus;


void setup()
{
 pinMode(tasterpin1, INPUT_PULLUP);
 pinMode(tasterpin2, INPUT_PULLUP);
 analogWrite(dimpin, Astatus.dim);
}

void loop()
{
 handleDim();
}

void handleDim()
{
 switch (Astatus.status)
 {
   case A_Taster1: if (!digitalRead(tasterpin1)) // low = taster gedrückt
     {
       Astatus.status = A_DimUp;
       Astatus.lastHit = millis();
     }
     break;

   case A_DimUp:  if (millis() - Astatus.lastHit > dimSpeed) // low = taster gedrückt
     {
       Astatus.lastHit = millis();
       Astatus.dim++;
       analogWrite(dimpin, Astatus.dim);
     }
     if (Astatus.dim == 255)
     {
       Astatus.status = A_Taster2 ;
     }
     break;
case A_Taster2: if (!digitalRead(tasterpin2)) // low = taster gedrückt
     {
       Astatus.status = A_DimDown;
       Astatus.lastHit = millis();
     }
     break;

  

   case A_DimDown:  if (millis() - Astatus.lastHit > dimSpeed) // low = taster gedrückt
     {
       Astatus.lastHit = millis();
       Astatus.dim--;
       analogWrite(dimpin, Astatus.dim);
     }
     if (Astatus.dim == 0)
     {
       Astatus.status = A_Taster1;
     }
     break;
 }
}

Hast du dich schon per Google über endliche Automaten kundig gemacht?
Generationen von Programmierer haben sich da schon einen Kopf drum gemacht.
Und jetzt bist du dran :smiley: :smiley: :smiley:

Ja, ich weiß, vieles im Netz ist sehr theoretisch.
Zu theoretisch.


Du solltest dir mal ein Bild malen.

Mit diesen Dingen:
Die nötigen Zustände (um dein Ziel zu erreichen)
Übergänge (welche und warum Zustandswechsel)

Oder erst einmal eine Liste der Zustände:
(man kann hier im Forum so schlecht malen)

  1. LampeIstAus
  2. HochDimmen
  3. LampeIstAn
  4. RunterDimmen
    Diese Zustände sollten doch für deinen Zweck reichen, oder?

Dann gehts jetzt an die Übergänge:
Im Zustand 1 wird auf den HochDimTastenDruck gewartet. Wenn gedrückt wird zu Zustand 2 gewechselt.
Im Zustand 2 wird die Helligkeit erhöht. Wenn voll an wird zu Zustand 3 gewechselt.
Im Zustand 3 wird auf den RunterDimTastenDruck gewartet. Wenn gedrückt wird zu Zustand 4 gewechselt.
Im Zustand 4 wird die Helligkeit verringert. Wenn total aus wird zu Zustand 1 gewechselt.

Die Lampe beginnt im Aus Zustand.
Die Zustände rauf und runter dimmen können nicht unterbrochen werden.

Stimmt das so?
Entsprechen die Regeln deinen Vorstellungen?

Wenn ja, hast du da jetzt ein Muster, welches man in Software gießen kann.

In meinem Stil würde das dann so aussehen:

const unsigned int dimpin      =  3; // pin -- R -- LED -- GROUND
const unsigned int UpTaster    =  4; // Pin -- Taster -- GROUND
const unsigned int DownTaster  =  2; // Pin -- Taster -- GROUND
const unsigned int dimSpeed    = 50; // mS pro dimschritt




struct Automat 
{
  typedef enum  AutomatenStatus {A_On, A_Off, A_DimUp, A_DimDown};
  AutomatenStatus status;
  unsigned long lastHit;
  byte dim;
  Automat() // Konstruktor
  {
    pinMode(UpTaster, INPUT_PULLUP);
    pinMode(DownTaster, INPUT_PULLUP);
    lastHit = millis();
    dim     = 0;
    status  = A_Off;
    analogWrite(dimpin,dim);
  }
  
void handle()
{
  switch (status)
  {
    case A_Off: 
      if (!digitalRead(UpTaster)) // low = taster gedrückt
      {
        status  = A_DimUp;
        lastHit = millis();
      }
      break;

    case A_DimUp:  
      if (millis() - lastHit > dimSpeed) 
      {
        lastHit = millis();
        dim++;
        analogWrite(dimpin,dim);
      }
      if (dim == 255)
      {
        status = A_On ;
      }
      break;
      
   case A_On: if 
      (!digitalRead(DownTaster)) // low = taster gedrückt
      {
        status  = A_DimDown;
        lastHit = millis();
      }
      break;

    case A_DimDown:  
      if (millis() - lastHit > dimSpeed) 
      {
        lastHit = millis();
        dim--;
        analogWrite(dimpin, dim);
      }
      if (dim == 0)
      {
       status = A_Off;
      }
      break;
  }
}
};





Automat Dimmer;
void setup()
{
}

void loop()
{
   Dimmer.handle();
}

ungetestet

Ok da kommt so eine Fehlermeldung, die heißt
undefined reference to setup' undefined reference to loop'

Nein!
Du hast vermutlich nicht alles kopiert.

Fehler beim kopieren würd ich sagen, bei mir gehts 8)

Hahaha sorry :grinning:

Ok das mit dem Dimmen haut jetzt super hin und den Automaten versteh ich jetzt auch schon besser. Ein Problem hab ich jetzt noch. Und zwar das eigentliche Projekt soll wie folgt ablaufen.

Mit dem einen Taster soll eine rgb in rot und blau, sprich violett, hochdimmen. Danach sollen die selben LED´s pulsweitenmoduliert über 2 analoge Eingänge gesteuert werden können. Zum Schluss soll dann durch den Taster die LED wieder runterdimmen. Die PWM habe ich selber geschafft zu programmieren. Nur wenn ich die zwei Programme zusammenfüge stören die sich gegenseitig und die LED beginnt zu flackern. Hast du da irgendwelche Tipps für mich oder sogar die Lösung?

Bin dir aber jetzt schon mal sehr dankbar. Ohne dich hätte ich das Projekt nicht einmal annähernd weitergebracht.

Neue Bedingungen -- führt zu -- neuen Zuständen
Also: Den Automaten erweitern.

Nein, eine fertige Lösung habe ich nicht.

Ok, aber prinzipiell würde das funktionieren?

Male dir die Zustände auf Papier auf.
Male die Übergänge dazu.
Dann siehst du ob deine Logik funktioniert.
Gieße die Logik in Software.