Routine aufrufen, Unterprogramm

Ich möchte immer 12 angeschlossenen LEDs ausschalten wenn ich einen Taster betätige.
Hintergrund ist folgender: Jeder Taster schaltet eine bestimmte LED an und gibt einen Wert über die Serielle Schnittstelle an den PC. Diese LED soll ausgehen, wenn ein anderer Taster betätigt wird und "seine" LED anschaltet. Als VB Programmiere hätte ich ein Unterprogram (Sub), in dem alle LEDs gelöscht werden und das ich bei jedem Tastendruck aufrufe.
Geht das mit dem Arduino auch? Habe natürlich schon gegoogelt und eine mögliche Lösung gefunden über ein separates "Void"

void loop() {
    for (i=0; i<3; i++) {
      if (digitalRead (TasterPin [i]) == HIGH) {
       
**Hier würde dann das Unterprogramm aufgerufen werden.**
 **Diode** (LedPin [i], 0);
      }
    }
    if (digitalRead (TasterPin [0]) == LOW) {
      Diode (LedPin [0], 25);
    }
    if (digitalRead(TasterPin [1]) == LOW) {
      Diode (LedPin [1], 150);
    }
    if (digitalRead(TasterPin [2]) == LOW) {
      Diode (LedPin [2], 250);
    }
  }

**Das währe das Unterprogramm, in dem die LEDs gelöscht werden:**

  **void Diode ( int PinNr, int Wert ) {**
**    analogWrite(PinNr, Wert);**
  }

Quelle: https://www.meine-schaltung.de/themen/arduino/unterprogramme/

Unabhängig vom Code. Es geht um das Prinzip. Währe das so möglich oder gibt es eine andere Möglichkeit?

Void ist NICHTS, ein Unterprogramm erkennt man in C an den runden Klammern nach dem Namen.

Mit Arduino hat das nichts zu tun, Unterprogramme sind Sache der Programmiersprache (C/C++) und des Compilers. Üben kannst Du also auch in VC.

Falls immer nur 1 LED an sein soll dann reicht es, sich die gerade eingeschaltete LED zu merken. Nur die muß dann wieder ausgeschaltet werden.

du machst dir einfach eine FUNKTION in der du alle Ausgänge ausschaltest
Die Funktion braucht keinen Parameter und braucht keinen Wert zurückgeben, daher ist die Rückgabe "void".

void allesAus()
{
  for (int i = 0; i < noOfPins; i++) 
    analogWrite(pin[i], 0);
}

einige kennzeichnen auch dass kein Parameter übergeben wird:

void allesAus(void)

aber wie schon angemerkt, wenn eh immer nur eine LED leuchten kann, dann könntest dir auch die letzte gesetzte LED merken und diese das nächste Mal einfach abschalten wenn du die neue LED einschaltest (und merkst).

ca so:

// https://forum.arduino.cc/t/routine-aufrufen-unterprogramm/968713/3
struct Group
{
  const byte ledPin;
  const byte buttonPin;
};
Group group[]
{
  {13, A0},
  {6, A1},
  {5, A2},
  {11, A3}
};

void readButtons()
{
  static byte previousActive = 0;
  for (size_t i = 0; i < sizeof(group) / sizeof(group[0]); i++)
  {
    if (digitalRead(group[i].buttonPin) == LOW)  // evtl. auch noch auf != previousAction
    {
      Serial.print(F("button pressed ")); Serial.println(i);
      digitalWrite(group[previousActive].ledPin, LOW);
      previousActive = i;
      digitalWrite(group[i].ledPin, HIGH);
      //tbd measures to debounce...
    }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("taster und LEDs in gruppen"));
  for (auto &i : group)
  {
    pinMode(i.ledPin, OUTPUT);
    pinMode(i.buttonPin, INPUT_PULLUP);
  }
}

void loop() {
  readButtons();
}
1 Like

@ DrDiettrich
Da Void ja benutzt wird scheint es schon was zu sein. Und da es Teil des Arduino Sketches ist hat es wohl auch mit Arduino zu tun. Aber Danke für deine Antwort.

@ noiasca
Super. Das wollte ich wissen. Das hilft mir wirklich weiter.

Void heißt frei übersetzt "nicht vorhanden"
Hier bezeichnet es den Datentype der Funktionsrückgabe.
Eben keine Rückgabe.

WinzigWeich sagt dazu: Incomplete Types | Microsoft Learn

Unser C++ sagt dazu: Fundamental types - cppreference.com

Du siehst:

passt schon recht gut.

man könnte die statische Variable auch in die Struktur geben.

// https://forum.arduino.cc/t/routine-aufrufen-unterprogramm/968713/3
struct Group
{
  const byte ledPin;
  const byte buttonPin;
  static byte previousActive;
};
Group group[]
{
  {13, A0},
  {6, A1},
  {5, A2},
  {11, A3}
};
byte Group::previousActive = 0;

void readButtons()
{
  for (size_t i = 0; i < sizeof(group) / sizeof(group[0]); i++)
  {
    if (digitalRead(group[i].buttonPin) == LOW)  // evtl. auch noch auf != previousAction
    {
      Serial.print(F("button pressed ")); Serial.println(i);
      digitalWrite(group[group[i].previousActive].ledPin, LOW);
      group[i].previousActive = i;
      digitalWrite(group[i].ledPin, HIGH);
      //tbd measures to debounce...
    }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("taster und LEDs in gruppen"));
  for (auto &i : group)
  {
    pinMode(i.ledPin, OUTPUT);
    pinMode(i.buttonPin, INPUT_PULLUP);
  }
}

void loop() {
  readButtons();
}

oder gleich OOP und die Funktion auch in die Struktur/Klasse

Ganz dünnes Eis!

Warum?

Die Endever wurde die Tage auch gefunden.

// https://forum.arduino.cc/t/routine-aufrufen-unterprogramm/968713/3
class Group
{
    const byte ledPin;
    const byte buttonPin;
    static byte previousPin;

  public:
    Group (byte ledPin, byte buttonPin) : ledPin{ledPin}, buttonPin{buttonPin} {}

    void setup(){
      pinMode(ledPin, OUTPUT);
      pinMode(buttonPin, INPUT_PULLUP);
    }
    
    void update(){
      if (digitalRead(buttonPin) == LOW)
      {
        digitalWrite(previousPin, LOW);
        digitalWrite(ledPin, HIGH);
        previousPin = ledPin;
      }
    }
};
byte Group::previousPin = 255;

Group group[]
{
  {13, A0},
  {6, A1},
  {5, A2},
  {11, A3}
};

void setup() {
  Serial.begin(115200);
  Serial.println(F("Taster und LEDs in Gruppen"));
  for (auto &i : group) i.setup();
}

void loop() {
  for (auto &i : group) i.update();
}
1 Like

Keine Ahnung, was du da nimmst.....
Ich will nix davon!

Meinst du vielleicht die Endeavour?
Und wenn, was hat das mit statischen Klasseneigenschaften zu tun?

Weil es Stock in die Speichen der Wiederverwendung der Klasse/Struktur wirft.

Das einzige OOP Designpattern, welches sowas einfordert, ist das Singleton Pattern. Und das ist noch schlimmer in Verruf geraten, als das Goto. Mit Recht.

Statische Variablen, in Funktionen, sind ja schon schlimm, aber in Klassen......

Aus meiner Sicht gibt es nur einen einzigen (halbwegs respektablen) Grund sowas zu tun: Faulheit!
Die anderen Gründe haben sicherlich irgendwas mit Wahnsinn oder Dummheit zu tun.

Übrigens:
Ja, ich setze auch an einer einzelnen Stelle, meiner Libs, auf das Singletonpattern. Habe da aber pingelig darauf geachtet, dass dort keinerlei "unerwünschten Seiteneffekte" auftreten können. Und ja, auch dieses wird noch eliminiert werden, der Plan ist schon 3/4 fertig.

1 Like

wenn der Threadowner noch mitliest, dann hätte ich noch eine Variante:

// https://forum.arduino.cc/t/routine-aufrufen-unterprogramm/968713/3
// Ziel: dem Pianoschaltwerk ein Array mit den Pins übergeben
// 2166/201

struct Combi        // combination/group of LED pin and button pin
{
  const byte ledPin;
  const byte buttonPin;
};
Combi combi[]      // define the LED --> button combination
{
  {13, A0},
  {6, A1},
  {5, A2},
  {11, A3}
};
constexpr size_t noOfCombi = sizeof(combi) / sizeof(combi[0]);

class Piano {
    Combi *obj;               // pointer to combination array
    const size_t noOfCombi;   // size of Array
    byte previousPin = 255;   // marker for last used pin
  public:
    Piano(Combi *obj, size_t noOfCombi) : obj{obj}, noOfCombi{noOfCombi} {}

    void begin() {
      for (size_t i = 0; i < noOfCombi; i++)
      {
        pinMode(obj[i].ledPin, OUTPUT);
        pinMode(obj[i].buttonPin, INPUT_PULLUP);
      }
    }

    void update() {
      for (size_t i = 0; i < noOfCombi; i++)
      {
        if (digitalRead(obj[i].buttonPin) == LOW)
        {
          digitalWrite(previousPin, LOW);
          digitalWrite(obj[i].ledPin, HIGH);
          previousPin = obj[i].ledPin;
        }
      }
    }
};
Piano piano {combi, noOfCombi};

void setup() {
  Serial.begin(115200);
  Serial.println(F("Taster und LEDs in Gruppen"));
  piano.begin();
}

void loop() {
  piano.update();
}
1 Like

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