An/Aus Taster für mein Projekt

Hallo,
ich bin kommpleter Neuling im Gebiet Arduino und ich hoffe das ich das Thema in die richtige Kategorie geschrieben hab.

Nun zur Frage:
Also ich möchte mit einem Ultrschallsensor den Abstand messen und in über eine RGB-LED und einen Buzzer ausgeben. Das funktioniert auch soweit einwandfrei.
Ich möchte aber das die Messung erst beginnt wenn ich den Taster einmal gedrückt habe und das ich den Messvorgang wieder abbrechen kann wenn ich den Taster erneut drücke. Das soll eigendlich mit der Variabel "z" funktionieren die einen zustand 0 oder 1 speicher, wie ich es oben im Code gemacht habe. Wo ich nur die beiden PowerLEDs hatte hat es auch geklappt. Ich konnte mit einmal drücken die rote LED ausschalten und die Grüne an und umgedreht.
Wenn ich diese if (z == 1) Abfrage nehme kann ich zwar den Messvorgang starten und die PowerLED wechselt, aber ich kann den Messvorgang nicht mehr ausschalten. Man sieht aber ein ganz leichtes flackern wenn man den Knopf drückt. Also weiß ich nicht ob es ein Hard oder Softwarefehler ist.
Ich hoffe Ihr wisst was ich meine und könnt mir dementsprechen helfen.

Anbei ist mein bisheriger Code und mein Schaltplan (Autodesk Tinkercad) meines Projekts.


Ob der wiederstand beim Taster sein muss weiß ich nicht.

Vielen Dank für euere Hilfe schon im Voraus!

```cpp
//03.01.2022

#include "SR04.h"
#include "pitches.h"

#define TRIG_PIN 12
#define ECHO_PIN 11
#define Red 5
#define Green 6
#define Blue 3

SR04 sr04 = SR04(ECHO_PIN, TRIG_PIN);

long e;  // Variabel wo das Messergebniss des SR04 gespeichert wird

int powerLedOn = 9;
int powerLedOff = 8;
int buzzer = 2;
int powerButton = 13;
int z;  // Zustandsvariabel (0 oder 1)


void setup()  //*****************************************************
{
  pinMode(powerLedOn, OUTPUT);
  pinMode(powerLedOff, OUTPUT);
  pinMode(Red, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(powerButton, INPUT_PULLUP);


}

void loop()  //*********************************************************
{

  if (digitalRead(powerButton) == LOW) {
    if (z == 1) {
      z = 0;
    } else {
      z = 1;
    }
  }

  if (z == 1) {
    digitalWrite(powerLedOn, HIGH);
    digitalWrite(powerLedOff, LOW);
  } else {
    digitalWrite(powerLedOn, LOW);
    digitalWrite(powerLedOff, HIGH);
  }

  if (z == 1)  //-------------------------------------------------------------
  {
    e = sr04.Distance();


    if (e > 100) {
      analogWrite(Red, 0);
      analogWrite(Green, 255);
      analogWrite(Blue, 0);
      tone(buzzer, NOTE_F6, 50);
      delay(500);
    } else {
      if (e > 50) {
        analogWrite(Red, 255);
        analogWrite(Green, 70);
        analogWrite(Blue, 0);
        tone(buzzer, NOTE_F6, 50);
        delay(325);
      } else {
        if (e > 30) {
          analogWrite(Red, 255);
          analogWrite(Green, 70);
          analogWrite(Blue, 0);
          tone(buzzer, NOTE_F6, 50);
          delay(250);
        } else {
          if (e > 10) {
            analogWrite(Red, 255);
            analogWrite(Green, 0);
            analogWrite(Blue, 0);
            tone(buzzer, NOTE_F6, 50);
            delay(100);
          } else {
            if (e > 0) {
              analogWrite(Red, 255);
              analogWrite(Green, 0);
              analogWrite(Blue, 0);
              tone(buzzer, NOTE_F6, 50);
            }
          }
        }
      }
    }
  }
}

Das ist gefährlich. So wechselt der Zustande mehrfach solange der Taster gedrückt ist.
Du darfst nicht auf den Zustand triggern sondern auf den Zustadnswechsel
zB: Arduino - Button Toggle LED | Arduino Tutorial

Grüße Uwe

1 Like

Der kommt da raus. Du benutzt den internen PULLUP.
probier mal den hier

// ungetestet

//03.01.2022

#include "SR04.h"
#include "pitches.h"

#define TRIG_PIN 12
#define ECHO_PIN 11
#define Red 5
#define Green 6
#define Blue 3

SR04 sr04 = SR04(ECHO_PIN, TRIG_PIN);

long e;  // Variabel wo das Messergebniss des SR04 gespeichert wird

const byte powerLedOn = 9;
const byte powerLedOff = 8;
const byte buzzer = 2;
const byte powerButton = 13;
bool z = false; // Zustandsvariabel (0 oder 1)
bool lastState = false;

void setup()  //*****************************************************
{
  pinMode(powerLedOn, OUTPUT);
  pinMode(powerLedOff, OUTPUT);
  pinMode(Red, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(powerButton, INPUT_PULLUP);
}

void loop()  //*********************************************************
{
  if (digitalRead(powerButton) == LOW)
  {
    if (!lastState)
    {
      lastState = true;
      z = !z;
    }
  }
  else
  {
    lastState = false;
  }
  digitalWrite(powerLedOn, z);
  digitalWrite(powerLedOff, !z);
  if (z == true)  //-------------------------------------------------------------
  {
    e = sr04.Distance();
    if (e > 100)
    {
      analogWrite(Red, 0);
      analogWrite(Green, 255);
      analogWrite(Blue, 0);
      tone(buzzer, NOTE_F6, 50);
      delay(500);
    }
    else if (e > 50)
    {
      analogWrite(Red, 255);
      analogWrite(Green, 70);
      analogWrite(Blue, 0);
      tone(buzzer, NOTE_F6, 50);
      delay(325);
    }
    else if (e > 30)
    {
      analogWrite(Red, 255);
      analogWrite(Green, 70);
      analogWrite(Blue, 0);
      tone(buzzer, NOTE_F6, 50);
      delay(250);
    }
    else if (e > 10)
    {
      analogWrite(Red, 255);
      analogWrite(Green, 0);
      analogWrite(Blue, 0);
      tone(buzzer, NOTE_F6, 50);
      delay(100);
    }
    else if (e > 0)
    {
      analogWrite(Red, 255);
      analogWrite(Green, 0);
      analogWrite(Blue, 0);
      tone(buzzer, NOTE_F6, 50);
    }
  }
}

Nachfrage: Was sollen die delay() bewirken?
Momentan bewirken die zumindest, das das prellen des tasters ausgemerzt wird. Ist aber kontraproduktiv...

1 Like

Hallo Uwe,
vielen Dank für deine Lösungsansatz und für den hilfreichen Link.

LG,
On Fire

@my_xy_projekt

Hallo my_xy_projekt,

vielen Dank für deine Antwort.
So wie du den Code abgeändert hast funktioniert es wie ich mir es vorgestellt habe.

Noch ein paar Anfängerfragen zum Code:

const byte buzzer = 2;

Du hast anstatt int buzzer = 2; const byte buzzer = 2; genommen. Also auf byte passen ganze zahlen von 0 bis 255 (?) und deshalb spart man Speicherplatz? Welche Vorteile hat const?

Es funktioniert zwar anscheinend ich verstehe es aber nicht ganz: Also oben wird lastState auf false gesetzt. Wenn der Taster low ist fragt die erste if- Anweißung: "ist lastState das gegenteil von dem was es jetzt ist. (und da es ja nicht ist wird lasteState auf false gesetzt obwohl es das ja eigendlich schon ist.)"

Heißt das: true == high und false == low ist oder wie kann ich das verstehen?

Vielen Dank für deine Antwort und die Lösung meines Problems!

LG,
On Fire

P.s welches delay meinst du? Dass bei den Abstandsabfragen soll den buzzer schneller oder langsamer hintereinander piepsen lassen.
Irgendwie haben die meine Antwort kurzzeitig runter genommen wo ich sie bearbeitet habe, jetzt ist sie nicht mehr deine Antwort sondern ein Beitrag...keine Ahnung...hab jetzt keine lust das nochmal neu zu schreiben sorry.

Können sich die Pins verändern? Nein. Von daher teile dem Kompiler mit, das er drauf achten soll, wenn Du zwischendurch mal Mist baust :wink:
Ausserdem brauchen Konstanten keinen Ram und Variablenspeicher.
Manchmal ist das sogar recht viel.
Nimm mal das const beim buzzer weg. Kostet Dich 18 bytes.

Ansonsten gilt: Nimm dem Kompiler soviel wie möglich ab.
In dem Fall hier verkleinert der schon selbst die Pin-größen von int auf byte. Aber eben mit Nebeneffekt beim BuzzerPin.
Aber mach mal aus dem bool z ein int z. Kostet Dich erschreckende 22 bytes + 1 byte Variablenspeicher.
bei lastState noch mehr...

Also soweit wie möglich mitdenken und den kleinstnotwendigsten Wertebereich wählen spart Speicher und wird ggfls. auch übersichtlicher. (ein int könte auch -1234 sein. Für einen PIN? :slight_smile: )

Den Codeschnipsel hab ich mal kommentiert:

void loop()  //*********************************************************
{
  if (digitalRead(powerButton) == LOW)   // Taste gedrückt?
  {
    if (!lastState)                      // letzter Zustand ist nicht gesetzt? (false)
    {
      lastState = true;                  // dann letzter Zustand setzen (true) UND
      z = !z;                            // z toggeln
    }
  }
  else                                   // Taste ist nicht gedrückt?
  {
    lastState = false;                   // dann lösche letzten Zustand (false)
  }
  digitalWrite(powerLedOn, z);           // ist z HIGH/true leuchtet diese LED, bei LOW/false nicht
  digitalWrite(powerLedOff, !z);         // ist z LOW/false leuchtet diese LED, bei HIGH/true nicht
  if (z == true)                         // Dieser Teil wird nur ausgeführt, wenn z HIGH/true ist
  {

Der einige springende Punkt ist das z=!z
lastState ist nur ein Merker, in dem sich gemerkt wird ob die Taste bereits als gedrückt ausgewertet wurde.
Denn nur beim drücken der Taste darf sich z ändern. Aber eben auch nur einmal. Dann muss die Taste wieder losgelassen werden um ein zweites Mal mit einem Tastendruck z zu ändern.
Das ist eigentlich recht easy, wenn man sich das verinnerlicht.
Eigentlich gehört da eine akademische Pause noch rein, damit Du das prellen/bouncen der Taste unterdrückst.

Hab ich mal gemacht.
Und ich hab noch versucht Deine delays() zu löschen.
Und das ein wenig umgeschrieben, damit es übersichtlicher wird.
Und... es hoffentlich nicht ganz vermanscht, das es wenigstens noch funktioniert
Na sieh selbst :slight_smile:

// Forensketch Abstandswarner
// basiert auf https://forum.arduino.cc/t/an-aus-taster-fur-mein-projekt/1072816/1
// basiert auf https://forum.arduino.cc/t/an-aus-taster-fur-mein-projekt/1072816/3
// ungetestet - kompiliert fehler- und warnungsfrei

#include "SR04.h"
#include "pitches.h"

const byte TRIG_PIN = 12;
const byte ECHO_PIN = 11;
const byte red = 5;
const byte grn = 6;
const byte bl = 3;

SR04 sr04 = SR04(ECHO_PIN, TRIG_PIN);

long e;  // Variabel wo das Messergebniss des SR04 gespeichert wird

const byte powerLedOn = 9;
const byte powerLedOff = 8;
const byte buzzer = 2;
const byte powerButton = 13;
bool z = false; // Zustandsvariabel (0 oder 1)
bool lastState = false;

uint32_t lastmillis;
const uint32_t bounceTime = 40;

void setup()  //*****************************************************
{
  pinMode(powerLedOn, OUTPUT);
  pinMode(powerLedOff, OUTPUT);
  pinMode(red, OUTPUT);
  pinMode(grn, OUTPUT);
  pinMode(bl, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(powerButton, INPUT_PULLUP);
}

void loop()  //*********************************************************
{
  eingabe();
  ausgabe();
}
void eingabe()
{
  if (digitalRead(powerButton) == LOW)   // Taste gedrückt?
  {
    if (!lastState)                      // letzter Zustand ist nicht gesetzt? (false)
    {
      lastmillis = millis();             // Zeit merken wann ausgelöst
      lastState = true;                  // dann letzter Zustand setzen (true) UND
      z = !z;                            // z toggeln
    }
  }
  else if (millis() - lastmillis > bounceTime)   // Taste ist nicht gedrückt && Zeit seit Tastendruck abgelaufen?
  {
    lastState = false;                   // dann lösche letzten Zustand (false)
  }
}
//
void ausgabe()
{
  digitalWrite(powerLedOn, z);           // ist z HIGH/true leuchtet diese LED, bei LOW/false nicht
  digitalWrite(powerLedOff, !z);         // ist z LOW/false leuchtet diese LED, bei HIGH/true nicht
  if (z == true)                         // Dieser Teil wird nur ausgeführt, wenn z HIGH/true ist
  {
    e = sr04.Distance();
    switch (e)
    {
      case 101 ... 250:
        lamp(0, 255, 0);
        buz(NOTE_F6, 50, 5, 500);
        break;
      case 51 ... 100:
        lamp(255, 70, 0);
        buz(NOTE_F6, 50, 4, 325);
        break;
      case 31 ... 50:
        lamp(255, 70, 0);
        buz(NOTE_F6, 50, 3, 250);
        break;
      case 11 ... 30:
        lamp(255, 0, 0);
        buz(NOTE_F6, 50, 2, 100);
        break;
      case 1 ... 10:
        lamp(255, 0, 0);
        buz(NOTE_F6, 50, 1, 0);
        break;
    }
  }
}

void buz(const uint16_t note, const byte dauer, const byte ausloeser, const uint32_t pausezeit)
{
  static byte lastAusloeser = 0;
  static uint32_t toneStart = 0;
  if (lastAusloeser != ausloeser)
  {
    lastAusloeser = ausloeser;
    tone(buzzer, note, dauer);
    toneStart = millis();
  }
  else if (millis() - toneStart > pausezeit)
  {
    lastAusloeser = 0;
  }
}

void lamp(const byte r, const byte g, const byte b)
{
  analogWrite(red, r);
  analogWrite(grn, g);
  analogWrite(bl, b);
}
2 Likes

Vielen Dank, das du dir die Mühe gemacht hast!
Dein Code funktioniert perfekt.

Also dein Karma steigt auf jedenfall weiter :wink:

1 Like

Supi.
Jetzt nur noch berichtigen in der Funktion buz.
Die Pausezeit darf die Tonezeit nicht enthalten.
Die Startzeit wird vor der Tonausgabe ausgelöst, dann kommen 50ms Ton und dann die Pause.
Hier sind es "nur" 50ms und eher nicht hörbar auffällig.
Wenn Du aber die Tonezeit auf 100ms erhöhst, dann ist die Pausezeit für die Entfernung 11...30 bereits erreicht.
Um das zu vermeiden, muss zur Pausezeit die Tonezeit dazugerechnet werden.
Zeile 105:

  else if (millis() - toneStart > pausezeit + dauer)

Dann sollte es stimmen...

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