Taster als Schalter für loop schleife

Hallo zusammen,
ich wollte mir ein "elektronisches Feuer" als tisch Deko bauen und jetzt sitze ich vor ein eigentlich simple Sache fest und weiß nicht wo da der Fehler ist:

bool geschaltet = false;      
int tasterPin = 8;            
int empfindlichkeit = 200;    


void setup()
{
pinMode( tasterPin, INPUT_PULLUP);  
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}

void loop() {
if (digitalRead(tasterPin) == LOW)   

    if (geschaltet == false) {       
      geschaltet = true;    
    }
    else {
      geschaltet = false;   
      }
    if (geschaltet == true) {
      
analogWrite(9, random(120)+135);
analogWrite(10, random(120)+135);
analogWrite(11, random(120)+135);
delay(random(100));
    }
if (geschaltet == false){
  analogWrite(9,LOW);
  analogWrite(10,LOW);
  analogWrite(11,LOW);  
}
delay(empfindlichkeit);

}

Die Schleife wird anscheinend ganz langsam ausgeführt(an den LEDs zu erkennen Blinkrythmus) der Taster funktioniert aber(nach mehrere mal betätigen).
Was läuft hier falsch?

vielen dank im vorraus

Keine Ahnung.
Das Programm tut das, was du programmiert hast!

Was gefällt dir daran nicht?

Habe das mal etwas umgeräumt.....


int tasterPin = 8;



void setup()
{
  pinMode( tasterPin, INPUT_PULLUP);
}

void loop()
{
  if(digitalRead(tasterPin))
  {
    analogWrite( 9, LOW);
    analogWrite(10, LOW);
    analogWrite(11, LOW);
  }else
  {
    analogWrite( 9, random(220) + 35);
    analogWrite(10, random(220) + 35);
    analogWrite(11, random(220) + 35);
    delay(random(200)+100);
  }
}

"Taster als Schalter" ist das nicht.
Wenn Du einen Taster als Schalter verwenden willst dann muß die Betätigungsdauer nicht in die Funktin des Sketches eingehen sondern der Schalter bei der Betätigung geschlossen bzw geöffnet werden je nachdem wie er vorher war.

Schau dir mal Beispiele "button toggle" an.
zB https://arduinogetstarted.com/tutorials/arduino-button-toggle-led

Grüße Uwe

Hallo Uwe,
danke für den Tipp nur wie wende ich das für die schleife an?
Für eine einzelne LED verstehe ich das.

gruß Stefan

ääh

Block mit geschwungene Klammern??

Grüße Uwe

Hallo Uwe,
ich sitz hier fest:


const int BUTTON_PIN = 8; 


int ledState = LOW;     
int lastButtonState;    
int currentButtonState; 

void setup() {
  
  pinMode(BUTTON_PIN, INPUT_PULLUP); 
  currentButtonState = digitalRead(BUTTON_PIN);
}

void loop() {
  lastButtonState    = currentButtonState;      
  currentButtonState = digitalRead(BUTTON_PIN); 

  if(lastButtonState == HIGH && currentButtonState == LOW) {
    

    
    ledState = !ledState;

    
    analogWrite( 9, LOW);
    analogWrite(10, LOW);
    analogWrite(11, LOW);

  
    analogWrite( 9, random(220) + 35);
    analogWrite(10, random(220) + 35);
    analogWrite(11, random(220) + 35);
    delay(random(100)+100);
  }
}

Jetzt wird die schleife nur 1 mal ausgeführt wenn ich den Taster drücke genau das soll er nicht.
Taster drücken schleife durchlaufen, Taster drücken schleife Stop.

gruß
stefan

Wäre das näher dran?

const int BUTTON_PIN = 8;

bool ledState = LOW;
bool lastButtonState;
bool currentButtonState;

void setup()
{
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  currentButtonState = digitalRead(BUTTON_PIN);
  lastButtonState    = currentButtonState;
}

void loop()
{
  lastButtonState    = currentButtonState;
  currentButtonState = digitalRead(BUTTON_PIN);

  if (lastButtonState == HIGH && currentButtonState == LOW) {
    ledState = !ledState;
  }
  if (ledState)
  {
    analogWrite( 9, random(220) + 35);
    analogWrite(10, random(220) + 35);
    analogWrite(11, random(220) + 35);
    delay(random(100) + 100);
  } else {
    digitalWrite( 9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    delay(100);
  }
}

Du hast gleich zwei Probleme.
Dein delay() verhindert, das Du in der Zeit die Taste abfragen kannst.
Andererseits verhindert das delay das bouncen der Taste, was Du abfangen musst.

Vielleicht....

const byte BUTTON_PIN = 8;
bool ledState = LOW;
bool lastButtonState;
bool currentButtonState;
const uint32_t bounceTime = 40; // Zeit in ms
uint32_t lastPressed = 0; // Merker
uint32_t lastBlink = 0; // Merker
uint32_t blinkPause = 0;

void setup()
{
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  currentButtonState = digitalRead(BUTTON_PIN);
}

void ledAus()
{
  analogWrite( 9, LOW);
  analogWrite(10, LOW);
  analogWrite(11, LOW);
}
void ledFeuer()
{
  analogWrite( 9, random(220) + 35);
  analogWrite(10, random(220) + 35);
  analogWrite(11, random(220) + 35);
}

void loop()
{
  currentButtonState = digitalRead(BUTTON_PIN);
  if (lastButtonState != currentButtonState)
  {
    if (millis() - lastPressed > bounceTime)
    {
      lastButtonState = currentButtonState;
      lastPressed = millis();
    }
  }
  if (lastButtonState == LOW)
  {
    if (millis() - lastBlink > blinkPause )
    {
      ledFeuer();
      blinkPause = random(100) + 100;
      lastBlink = millis();
    }
  }
  else
  {
    ledAus();
  }
}

@agmue war schneller :wink: Aber ich ungetestet...

Nö, meiner ist getestet.

Wortdreher macht Satz zu nichte..... Um Missverständnis zu vermeiden gekürzt.

Schon ein einziger Buchstabendreher kann einen ganzen Satz urinieren.

So hier in mein template die functions von xy-geklaut und eingesetzt.
Wenn man einen Code verallgemeinert und universalisiert dann wird er länger.

aber erst einmal ein Überblick wie es funktioniert

es gibt eine function

GetToggleSwitchState()

die entweder true oder false zurückgibt
Mit jedem Tastendruck wechselt es zwischen true und false
Die Auswertung des Tasters ist entprellt.

In function loop() wird der "Schaltzustand" abgefragt und dann eine function aufgerufen
die als Parameter die "Feuer ein" / "Feuer aus" -Information hat.

void loop () {
  activationMode = GetToggleSwitchState(); // must be executed all the time
  execute_if_Active(activationMode);       // function that does what its name says
}

Das bedeutet die Variable activationMode hat also entweder den Wert true odr false

Abhängig von diesem true/false werden dann die LEDs entweder feuergeflackert oder ausgeschaltet

void execute_if_Active(bool p_IsActivated) {

  if (p_IsActivated) { 
    
    // prüfe ob die Wartezeit die in Variable Blinkpause gespeichert ist
    // schon vorbei ist
    if ( TimePeriodIsOver(BlinkTimerStarted, blinkPause) ) {
      // wenn Wartezeit WIRKLICH vorbei dann
      ledFeuer(); // LED Helligkeit neu setzen
      blinkPause = random(100) + 100; // neue Blinkopausenzeit speichern
    }
  }
  else { // DE-activated
    ledAus();
  }

  PrintToSerialMonitor(p_IsActivated); // deactivate through commenting if not wanted
}

Das Flackern wird nicht-blockierend gemacht damit das Programm jederzeit innerhalb von Millisekunden auf das betätigen des Tasters reagieren kann.

So viel zur prinzipiellen Funktion die ganzen restlichen Zeilen machen die Details.
Schön aufgeteilt in functions die alle einen selbsterklärenden Namen haben.

getestet durch Umbiegen von Led3 auf onboard-LED (io-pin 13) eines Arduino-Unos

So jetzt kannst auswählen welchen Code du benutzen willst.

#define ProjectName "elektronikfreak start stop 004"

// define IO-states for inputs with pull-up-resistors
// pull-up-resistors invert the logig
#define unPressed HIGH
#define pressed   LOW

const byte ToggleButtonPin = 8;
const byte Led1 =  9;
const byte Led2 = 10;
const byte Led3 = 11;

bool activationMode = false;
unsigned long BlinkTimerStarted = 0;
unsigned long blinkPause = 150;

void setup() {
  Serial.begin(115200); // adjust baudrate in the serial monitor to match the number
  Serial.println( F("Setup-Start") );
  printFileNameDateTime();

  pinMode (LED_BUILTIN, OUTPUT);  // used for indicating logging active or not
  digitalWrite(LED_BUILTIN, LOW);
  // wire button between IO-pin and GND
  // Pull-up-resistor inverts the logic
  // unpressed: IO-pin detects HIGH
  // pressed:   IO-Pin detects LOW
  pinMode(ToggleButtonPin, INPUT_PULLUP);
  pinMode(Led1, OUTPUT);
  pinMode(Led2, OUTPUT);
  pinMode(Led3, OUTPUT);
  ledAus();
  BlinkTimerStarted = millis();
}


void loop () {
  activationMode = GetToggleSwitchState(); // must be executed all the time
  execute_if_Active(activationMode);       // function that does what its name says
}


bool GetToggleSwitchState() {
  // "static" makes variables persistant over function calls
  static bool toggleState     = false;

  static byte buttonStateOld = unPressed;
  unsigned long buttonDebounceTime = 50;
  unsigned long buttonDebounceTimer = 0;

  byte buttonStateNew;

  if ( TimePeriodIsOver(buttonDebounceTimer, buttonDebounceTime) ) {
    // if more time than buttonDebounceTime has passed by
    // this means let pass by some time until
    // bouncing of the button is over
    buttonStateNew = digitalRead(ToggleButtonPin);

    if (buttonStateNew != buttonStateOld) {
      // if button-state has changed
      buttonStateOld = buttonStateNew;
      if (buttonStateNew == unPressed) {
        // if button is released
        toggleState = !toggleState; // toggle state-variable
      } // the attention-mark is the NOT operator
    }   // which simply inverts the boolean state
  }     // !true  = false   NOT true  is false
  //       !false = true    NOT false is true
  return toggleState;
}

void ledFeuer() {
  analogWrite(Led1, random(220) + 35);
  analogWrite(Led2, random(220) + 35);
  analogWrite(Led3, random(220) + 35);
}

void ledAus() {
  analogWrite(Led1, LOW);
  analogWrite(Led2, LOW);
  analogWrite(Led3, LOW);
}

void execute_if_Active(bool p_IsActivated) {

  if (p_IsActivated) {
    
    // prüfe ob die Wartezeit die in Variable Blinkpause gespeichert ist
    // schon vorbei ist
    if ( TimePeriodIsOver(BlinkTimerStarted, blinkPause) ) {
      // wenn Wartezeit vorbei dann
      ledFeuer(); // LED Helligkeit neu setzen
      blinkPause = random(100) + 100; // neue Blinkopausenzeit speichern
    }
  }
  else { // DE-activated
    ledAus();
  }

  PrintToSerialMonitor(p_IsActivated); // deactivate through commenting if not wanted
}


// helper-function ignore at first
void printFileNameDateTime() {
  Serial.print( F("File   : ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("Date   : ") );
  Serial.println( F(__DATE__) );
  Serial.print( F("Project: ") );
  Serial.println( F(ProjectName) );
}

// ignore at first
// helper-function for easy to use non-blocking timing
boolean TimePeriodIsOver (unsigned long & expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - expireTime >= TimePeriod ) {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  }
  else return false;            // not expired
}

void PrintToSerialMonitor(boolean p_IsActivated) {
  static bool lastIsActivated;

  // only in case the activation-mode has CHANGED print ONE time
  if (p_IsActivated != lastIsActivated) {
    // only if state of parameter p_logIsActivated has changed
    if (p_IsActivated) {
      Serial.println();
      Serial.println("start executing");
      Serial.println();
      digitalWrite(LED_BUILTIN, HIGH);
    }
    else { // not activated
      ledAus();
      Serial.println();
      Serial.println("stopp executing");
      Serial.println();
      digitalWrite(LED_BUILTIN, LOW);
    }

    lastIsActivated = p_IsActivated; // update variable lastSDlogActive
  }
}

vgs

Dein Programm wirft Warnungen mit IDE 1.8.19:

Test_Forum.ino: In function 'bool GetToggleSwitchState()':
Test_Forum.ino:48:15: warning: unused variable 'lastToggleState' [-Wunused-variable]
   static bool lastToggleState = false;
               ^~~~~~~~~~~~~~~
Test_Forum.ino:51:24: warning: unused variable 'buttonScanStarted' [-Wunused-variable]
   static unsigned long buttonScanStarted  =  0;
                        ^~~~~~~~~~~~~~~~~
Test_Forum.ino: At global scope:
Test_Forum.ino:51:24: warning: 'buttonScanStarted' defined but not used [-Wunused-variable]
Test_Forum.ino:48:15: warning: 'lastToggleState' defined but not used [-Wunused-variable]
   static bool lastToggleState = false;
               ^~~~~~~~~~~~~~~
C:\Program Files (x86)\Arduino-1.8.19\hardware\arduino\avr\cores\arduino\main.cpp: In function 'main':
Test_Forum.ino:122:22: warning: 'buttonDebounceTimer' is used uninitialized in this function [-Wuninitialized]
   if ( currentMillis - expireTime >= TimePeriod ) {
                      ^
Test_Forum.ino:53:17: note: 'buttonDebounceTimer' was declared here
   unsigned long buttonDebounceTimer;
                 ^
Der Sketch verwendet 3484 Bytes (10%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 234 Bytes (11%) des dynamischen Speichers, 1814 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Hallo agmue,

vielen Dank fürs sorgfältige Nachschauen
habe es korrigiert. Jetzt werden keine Warnungen mehr ausgegeben.
vgs

@StefanL38
Super danke funktioniert.
Jetzt nochmal eine blöde frage für Anfänger was bewirken die Serial ausgaben? "Helper Funktion"

macht was der Name der function sagt
auf die serielle Schnittstelle den Namen deiner *.INO-Datei und den Zeitpunkt des compilierens ausgeben

nicht blockierendes timing.
Wenn du es noch genauer wissen willst dann lese die Kommentare im code
vgs

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.