Rolladensteuerung

const uint8_t Taster_Hoch = 4;
const uint8_t Taster_Runter = 5;
const uint8_t Motor_Hoch = 6;
const uint8_t Motor_Runter = 7;
const uint8_t Motor_Start = 9;
bool Taster_Runter_Neu = LOW;
bool Taster_Runter_Alt = LOW;
bool Taster_Hoch_Neu = LOW;
bool Taster_Hoch_Alt = LOW;
bool Motor_Ein = false;

void setup() {
  pinMode(Taster_Hoch, INPUT_PULLUP);
  pinMode(Taster_Runter, INPUT_PULLUP);
  pinMode(Motor_Hoch, OUTPUT);
  pinMode(Motor_Runter, OUTPUT);
  pinMode(Motor_Start, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  Taster_Runter_Neu = digitalRead(Taster_Runter);
  Taster_Hoch_Neu = digitalRead(Taster_Hoch);
  if ((Taster_Hoch_Neu != Taster_Hoch_Alt) && (Motor_Ein == false)) {
    delay(50);
    if (Taster_Hoch_Neu == LOW) {
      digitalWrite(Motor_Hoch, HIGH);
      digitalWrite(Motor_Start, HIGH);
      Motor_Ein = true;
      Serial.println(F("Motor fährt Hoch"));
    }
    if ((Taster_Hoch_Neu != Taster_Hoch_Alt) && (Motor_Ein == true)) {
      if (Taster_Hoch_Neu == LOW) {
        digitalWrite(Motor_Hoch, LOW);
        digitalWrite(Motor_Start, LOW);
        Motor_Ein = false;
        Serial.println(F("Motor gestoppt"));
      }
    }
  }
  if ((Taster_Runter_Neu != Taster_Runter_Alt) && (Motor_Ein == false)) {
    delay(50);
    if (Taster_Runter_Neu == LOW) {
      digitalWrite(Motor_Runter, HIGH);
      digitalWrite(Motor_Start, HIGH);
      Motor_Ein =true;
      Serial.println(F("Motor fährt runter"));
    }
    if ((Taster_Runter_Neu != Taster_Runter_Alt) && (Motor_Ein == true)) {
      if (Taster_Runter_Neu == LOW) {
        digitalWrite(Motor_Runter, LOW);
        digitalWrite(Motor_Start, LOW);
        Motor_Ein = false;
        Serial.println(F("Motor gestoppt"));
      }
    }
  }
  Taster_Hoch_Alt = Taster_Hoch_Neu;
  Taster_Runter_Alt = Taster_Runter_Neu;
}

Hallo bräuchte mal Ideen hier bei meinem Programm.

Das ganze soll eine Rolladensteuerung dartsellen. Wenn ich den Taster einmal drücke soll der Motor solange laufen bis ich ihn erneut betätige. Das ganze sowohl für Hoch und auch Runter.
Nur habe ich aktuell noch das Problem, dass der Motor direkt beim anlaufen wieder gestoppt wird.

Bitte kommentiere mal deinen Sketch so, dass wir erkennen können, was an welcher Stelle wann passieren soll. Dann müssen wir nicht lange raten .

Wenn ich mir den Sketch ansehe mit den vielen ifs, kann ich dir nur raten, das ganze auf eine Statemaschine umzubauen.

Du findest hier im Forum massig Beispiele. Ein ganz einfaches Beispiel würde erst heute morgen von @noiasca gezeigt: Schrankensteuerung HO

1 Like

Vielleicht.

constexpr byte tasterPin[2] {4, 5};
constexpr byte motorRichtung[2] {6, 7};
constexpr byte motorEnable {9};

bool tasterLastState;;

constexpr bool isPressed {LOW};
constexpr bool isEin {HIGH};
constexpr bool isAus  {!isEin};

constexpr uint32_t debounceTime {100}; // zeit in ms
uint32_t pressTime;

void setup()
{
  Serial.begin(9600);
  for (byte b = 0; b < 2; b++)
  {
    pinMode(tasterPin[b], INPUT_PULLUP);
    pinMode(motorRichtung[b], OUTPUT);
    digitalWrite(motorRichtung[b], isAus);
  };
  pinMode(motorEnable, OUTPUT);
  digitalWrite(motorEnable, isAus);
}


void loop()
{
  for (byte b = 0; b < 2; b++)
  {
    if (digitalRead(tasterPin[b]) == isPressed)         // Taste gedrückt
    {
      pressTime = millis();                             // aktuelle Zeit merken
      if (tasterLastState == !isPressed)                // vorher nicht gedrückt,
      {
        if (digitalRead(motorEnable) == isEin)          // Antrieb aktiv?
        {
          for (byte c = 0; c < 2; c++)
          { digitalWrite(motorRichtung[c], isAus); }    // Richtung löschen
          digitalWrite(motorEnable, isAus);             // Antrieb aus machen
        }
        else                                            // Antrieb war aus?
        {
          digitalWrite(motorRichtung[b], isEin);        // Richtung setzen
          digitalWrite(motorEnable, isEin);             // Antrieb einschalten
        }
      }
      tasterLastState = isPressed;
    }
    else if (millis() - pressTime > debounceTime)       // Taste losgelassen und Zeit abgelaufen
    { tasterLastState = !isPressed; }
  }
}

also ich bin ja der Freund von wiederverwendbaren Sachen.

So einen entprellten Button kann man immer brauchen. In dem Beispiel sogar zwei. Eine Klasse dafür hab ich schon lange und schon oft hier gezeigt. Es gibt auch hunderte andere (schönere) Lösungen.

Einen Motor für Links-Rechts kann man vieleicht auch mal benötigen.

Und dann hat man einfach zwei Klassen die man im Loop miteinander kommunizieren lässt.

LED (Motor) and Toggle Button - Wokwi ESP32, STM32, Arduino Simulator

Und ja, im Prinzip nutzt der Motor eine State Machine.

Hallo,
Als Ansatz für einen Taster. Du sollst ja auch noch was zu tun haben. :wink:
Zudem noch dafür sorgen das wenn Du auf heben drückst das senken ausgeschaltete wird und umgekehrt. ich hab das mal angedeutet und als Kommentar eingefügt.

Gruß Heinz

const byte btnpin = 4;
const byte led = 13;  // interne LED

bool btnAlt;
bool btn;
bool heben;

void setup() {
  Serial.begin(9600);
  pinMode(btnpin, INPUT_PULLUP);
  pinMode(led, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(50); // schmutziges entprellen
  btn = !digitalRead(btnpin); // einlesen und invertieren

  if ( btn && !btnAlt) { // Abfrage flanke
    heben = !heben; // toggle 
    //  if (heben) senken=false;
    Serial.print(" toggle "); Serial.println(heben);
  }
  btnAlt = btn;

  digitalWrite(led, heben);

}

Zeigst Du wenisgtens eine Kopie des Codes?

.
sobald es eine "ich habs mir angesehen" Meldung vom TO kommt damit ich weis ob es funktioniert.

Las sein.
Ich wills nicht mehr sehn.

Hallo HabHunger

Ich habe auch noch einen :slight_smile:

//https://forum.arduino.cc/t/rolladensteuerung/1356419
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Rolladensteuerung"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
enum TimerControl {Halt, Run};
enum ButtonEvent {Released, Pressed};
enum MotorControl {Hoch, Runter, Stop};
enum OnOff {Off, On};
// make variables
uint8_t Inputpins[] {A0, A1};
uint8_t Outputpins[] {9, 10, 12};
constexpr uint8_t MotorControl[][3]
{
  {On, Off, On},
  {Off, On, On},
  {Off, Off, Off},
};

// make structures
struct TIMER
{
  uint32_t interval;
  uint8_t control;
  uint32_t now;
  uint8_t expired(uint32_t currentMillis)
  {
    uint8_t timerEvent = currentMillis - now >= interval and control;
    if (timerEvent == Expired) now = currentMillis;
    return timerEvent;
  }
};
struct MOTOR
{
  void make()
  {
    for (auto Outputpin : Outputpins) pinMode(Outputpin, OUTPUT);
  }
  void motorControl(uint8_t control)
  {
    uint8_t index = 0;
    if ((digitalRead(Outputpins[Stop]) ? On : Off) == Off)
      for (auto Outputpin : Outputpins) digitalWrite(Outputpin, MotorControl[control][index++]);
    else
      for (auto Outputpin : Outputpins) digitalWrite(Outputpin, MotorControl[Stop][index++]);
  }
} rollerShutter;

struct BUTTON
{
  uint8_t name;
  uint8_t pin;
  uint8_t stateOld;
  TIMER debounce;
  void  make(uint8_t name_, uint8_t pin_)
  {
    name = name_;
    pin = pin_;
    pinMode(pin, INPUT_PULLUP);
    stateOld = digitalRead(pin) ? Off : On;
    debounce.control = Run;
    debounce.interval = 20;
  }
  uint8_t run(uint32_t currentMillis)
  {
    uint8_t returnValue = Stop;
    if (debounce.expired(currentMillis) == Expired)
    {
      uint8_t stateNew = digitalRead(pin) ? Off : On;
      if (stateOld != stateNew)
      {
        stateOld = stateNew;
        if (stateNew == Pressed) returnValue = name;
      }
    }
    return (returnValue);
  }
} buttons[sizeof(Inputpins)];
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  uint8_t buttonName = Hoch;
  for (auto &button : buttons)
  {
    button.make(buttonName, Inputpins[buttonName]);
    buttonName++;
  }
  rollerShutter.make();
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  uint32_t currentMillis = millis();
  heartBeat(LED_BUILTIN, currentMillis);
  for (auto &button : buttons) if (button.run(currentMillis) != Stop) rollerShutter.motorControl(button.name);
}

Es gibt ja schon verschiedene Ansätze.
Hier eine Bemerkung zu Deinem Code:

  if ((Taster_Hoch_Neu != Taster_Hoch_Alt) && (Motor_Ein == false)) {

Motor steht, Tasterzustand hat sich geändert

    delay(50);
    if (Taster_Hoch_Neu == LOW) {

Taster wurde gedrückt

      digitalWrite(Motor_Hoch, HIGH);
      digitalWrite(Motor_Start, HIGH);
      Motor_Ein = true;
      Serial.println(F("Motor fährt Hoch"));
    }

Motor fährt - soweit gut.
Zustand ist immer noch: Tasterzustand hat sich geändert, aber Motor_Ein wurde gerade eben aktiviert.

    if ((Taster_Hoch_Neu != Taster_Hoch_Alt) && (Motor_Ein == true)) {

...und damit ist diese Bedingung auch erfüllt und da der Taster immer noch gedrückt ist...

      if (Taster_Hoch_Neu == LOW) {
        digitalWrite(Motor_Hoch, LOW);
        digitalWrite(Motor_Start, LOW);

...schaltest Du hier den Motor gleich wieder aus:

        Motor_Ein = false;
        Serial.println(F("Motor gestoppt"));
      }
    }
  }

Die Aktualisierung von ..._Alt erfolgt erst weiter unten, deshalb fällst Du hier auf die Nase.
Der Tastendruck ist im ersten if schon komplett abgehandelt.

Ich würde dringend empfehlen, eine Zustandstabelle anzulegen (Taster, Zustand alt und neu, Motorzustand) und danach mit einer (Suchwörter) Zustandsmaschine, Schrittkette, finite state machine weiterzumachen. Es könnte eine switch...case Konstruktion dabei herauskommen.

(Debugging by Text - ich will's auch nicht wieder tun)

Vielen Dank für die ganzen Antworten.

Hat jetzt tatsächlich doch was länger gedauert bis ich mich jetzt damit auseinandergesetzt habe.
Wollte Euch mal an dem Ergebnis was ich erreicht teilhaben lassen ob das noch irgendwas dran auszusetzen ist.

const uint8_t Taster_Hoch_PIN = 4;
const uint8_t Taster_Runter_PIN = 5;
const uint8_t Motor_Hoch = 6;
const uint8_t Motor_Runter = 7;
const uint8_t Motor_Start = 8;

enum Rolladenzustand { HOCH,
                       RUNTER,
                       STOP };

Rolladenzustand zustand = STOP;

bool hochToggle = false;
bool runterToggle = false;
bool Taster_Hoch_Alt = LOW;
bool Taster_Runter_Alt = LOW;

void setup() {

  pinMode(Motor_Hoch, OUTPUT);
  pinMode(Motor_Runter, OUTPUT);
  pinMode(Motor_Start, OUTPUT);
  pinMode(Taster_Hoch_PIN, INPUT_PULLUP);
  pinMode(Taster_Runter_PIN, INPUT_PULLUP);

  Serial.begin(9600);
}

void loop() {

  bool Taster_Hoch = !digitalRead(Taster_Hoch_PIN);
  bool Taster_Runter = !digitalRead(Taster_Runter_PIN);

  if (Taster_Hoch && !Taster_Hoch_Alt) {
    hochToggle = !hochToggle;
  }
  if (hochToggle) {
    zustand = HOCH;
  } else {
    zustand = STOP;
  }

  if (Taster_Runter && !Taster_Runter_Alt) {
    runterToggle = !runterToggle;
  }
  if (runterToggle) {
    zustand = RUNTER;
  } else {
    zustand = STOP;
  }

  switch (zustand) {

    case HOCH:
      digitalWrite(Motor_Hoch, HIGH);
      digitalWrite(Motor_Start, HIGH);
      Serial.println(F("Rollade geht hoch"));
      break;

    case RUNTER:
      digitalWrite(Motor_Runter, HIGH);
      digitalWrite(Motor_Start, HIGH);
      Serial.println(F("Rollade geht runter"));
      break;

    case STOP:
      digitalWrite(Motor_Start, LOW);
      digitalWrite(Motor_Runter, LOW);
      digitalWrite(Motor_Hoch, LOW);
      Serial.println(F("Rollade steht"));
      break;
  }
  Taster_Hoch_Alt = Taster_Hoch;
  Taster_Runter_Alt = Taster_Runter;
}

Eine Rolladensteuerung zeichnet sich dadurch aus, dass die jeweiligen Tasten gegenseitig verriegelt sind.

ja verstehe ich aber soll nicht umgesetzt werden.

Warum möchtest du dass wir daran Sachen aussetzen?
Es entspricht keinem der dargestellten Varianten.
Du gehst auf keinen der gezeigten Codes ein.
Wenn dein Sketch mit deiner Hardware das macht was du möchtest ist ja alles Gut für dich.

Ich hätte noch auszusetzen, dass Du bei jedem Durchlauf der loop() die Motorpins beschreibst. Das ist unnötig und braucht nur dann zu passieren, wenn sich der Zustand geändert hat.

... stört aber überhaupt nicht. Der Arduino hat sowieso sonst nichts zu tun.

Die vielen Serial.println Ausgaben sind da deutlich störender: Statt 20 µs tausendmal langsamer: ca. 20 ms (bei 9600)

Genaugenommen nutzt du diese 20 ms zum Taster entprellen.

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