"Timer" per Taster ein und aus schalten

Guten Tag,
Ich versuche Zurzeit ein altes Projekt etwas umzubauen.
Hierbei möchte ich 8 Relais mit 8 Tastern ein und ausschalten können.
Bis jetzt funktioniert es über externe Schalter.
Leider habe ich so gut wie keine Erfahrung, und habe nichts passendes für mein Problem gefunden das ich auch verstanden habe.
Ich würde gerne wissen was ich falsche mache oder wie ich es umsetzten kann.
Ich möchte keinen fertigen Code haben.
Vielen dank schonmal für Eure Hilfe.

Dies ist der Code mit den externen Schaltern.

const byte relais1 = 2;                          
const unsigned long onZeit = 400;
const unsigned long offZeit = 5000;
const byte relais2 = 3;                         
const unsigned long onZeit1 = 400;
const unsigned long offZeit1 = 10000;
const byte relais3 = 4;                         
const unsigned long onZeit2 = 400;
const unsigned long offZeit2 = 176600;
const byte relais4 = 10;                         
const unsigned long onZeit3 = 400;
const unsigned long offZeit3 = 209600;
const byte relais5 = 11;                         
const unsigned long onZeit4 = 400;
const unsigned long offZeit4 = 160000;
const byte relais6 = 7;                         
const unsigned long onZeit5 = 400;
const unsigned long offZeit5 = 800;
const byte relais7 = 8;                         
const unsigned long onZeit6 = 400;
const unsigned long offZeit6 = 800;
const byte relais8 = 9;                         
const unsigned long onZeit7 = 00;
const unsigned long offZeit7 = 000;
void setup() {
  pinMode(relais1, OUTPUT);
  pinMode(relais2, OUTPUT);
  pinMode(relais3, OUTPUT);
  pinMode(relais4, OUTPUT);
  pinMode(relais5, OUTPUT);
  pinMode(relais6, OUTPUT);
  pinMode(relais7, OUTPUT);
  pinMode(relais8, OUTPUT);
}

void loop() {
  digitalWrite(relais1, (millis() % (onZeit + offZeit)) < onZeit);
  digitalWrite(relais2, (millis() % (onZeit1 + offZeit1)) < onZeit1);
  digitalWrite(relais3, (millis() % (onZeit2 + offZeit2)) < onZeit2);
  digitalWrite(relais4, (millis() % (onZeit3 + offZeit3)) < onZeit3);
  digitalWrite(relais5, (millis() % (onZeit4 + offZeit4)) < onZeit4);
  digitalWrite(relais6, (millis() % (onZeit5 + offZeit5)) < onZeit5);
  digitalWrite(relais7, (millis() % (onZeit6 + offZeit6)) > offZeit6);
  digitalWrite(relais8, (millis() % (onZeit7 + offZeit7)) < onZeit7);
}

Bis jetzt habe ich es so probiert (was leider nicht funktioniert hat).

int Lichtschranke = 3; // oder Taster
int var; // Variable für den Pin Zustand
int buttonState; // Variable für den letzten Schalterzustand
int Runde = 0; // Wie oft ist der Schalter gedrückt

const byte relais1 = 2;                          //led
const unsigned long onZeit = 400;
const unsigned long offZeit = 5000;


void setup() {


  pinMode(Lichtschranke, INPUT);
  pinMode(relais1, OUTPUT);


  buttonState = digitalRead(Lichtschranke); // Start der seriellen Kommunikation mit 9600bps

}

void loop() {

  var = digitalRead(Lichtschranke);
  if (var != buttonState) { // Der Zustand des Schalters hat sich verändert
    if (var == HIGH) { // Ist der Schalter gedrückt?
      Runde++; // Inkrementieren der Variablen Runde



      if (Runde == 0) {
        digitalWrite(relais1, 0);
      }

      if (Runde == 1) {
        digitalWrite(relais1, (millis() % (onZeit + offZeit)) < onZeit);
      }


      if (Runde == 2) {
        digitalWrite(relais1, 0);
        Runde++;
      }

      if (Runde > 2) Runde = 0;
    }
  }
  buttonState = var; //Den Zustand merken
}

Schon mal was von arrays gehört?

Gehört schon benutzt noch nie.
Habe es mir mal kurz angeschaut.
Damit bekomme ich nur die Zeiten zusammen gefasst oder?
Oder bekomme ich damit auch die Schaltung hin?

Habe es mir mal angeschaut.
Dort ist jetzt nur die Schaltung der Taster und der Relais, bekomme ich da auch noch die Zeit Schaltung rein?

Habe bei einem anderen Thema das gefunden.
https://forum.arduino.cc/t/relays-uber-ein-arduino-ansteuern/616269/7?u=manu2796

Kann man die Zeit Schaltung in den anderen integrieren?
Vielen Dank schonmal

Ganz sicher!

Was soll denn das Programm alles in allem machen?

Im Titel steht Timer per Taster ein/ausschalten

Im Text steht

Das würde ich interpretieren als
Taster1-Ein => Relais 1 ein
Taster1-Aus => Relais 1 aus
oder evtl.

erster Tastendruck auf Taster1 => Relais1 ein
zweiter Tastendruck auf Taster1 => Relais1 aus

oder bedeutet es der Code macht ewiges Dauer ein/aus und dann gibt es externe Taster die das Signal auf das jeweilige Relais geben oder der Schalter unterbricht die Signalleitung zum Relais?

Und das soll jetzt von externen Schaltern auf an den Microcontroller angeschlossene Taster umgestellt werden?

Relais takten ein- / ausschalten mit einem Button oder mit zwei Button pro Relais?

Mein altes Programm hat einfach alle Relais in Dauerschleife schalten lassen und ich habe mit normalen ein/aus Schaltern das Signal zu den Relais unterbrochen um diese Auszuschalten.
Dieses hätte ich gerne jetzt im Programm integriert.

Ich möchte mit einem Taster die Steuerung des Relais ein/ ausschalten.
Die Steuerung soll eine Dauerschleife sein (z.B. 1 Sek an 50sek aus).

Werden diese Schaltzeiten ein für alle mal festgelegt und bleiben dann so oder werden die mehrmals täglich geändert?

Diese sollen festgelegt bleiben aber für jedes Relais unterschiedlich (stelle sie wenn dann im Programm um).

Hallo manu2796

Hier kommt ein Sketch indem nur noch die Konfiguration für ButtonPins, RelayPins und für Blinkzeiten angepasst werden muss.

Ist der Sketch für eine Modelleisenbahn?

//https://forum.arduino.cc/t/timer-per-taster-ein-und-aus-schalten/1206684
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Timer per Taster ein und aus schalten"
#define NotesOnRelease "Arduino  MEGA tested"
// make names
enum OffOn {Off, On,OffOn};
//make configuration ----------------------------------------
constexpr uint8_t ButtonPins[] {A0}; // [PORT PIN] --- [BUTTON] --- [GND]
constexpr uint8_t RelayPins[] {9};
constexpr uint32_t Flashes [][OffOn] {{333, 555}};
//-------------------------------------------------------------
// make structures
struct BUTTONFLASHRELAY
{
  uint8_t relayPin;
  uint8_t buttonPin;
  uint8_t stateOld;
  uint32_t flashNow;
  uint32_t flash[2];
  uint8_t flash_control;
  uint32_t debounceNow;
  uint32_t debounceInterval;
  void make(uint8_t relayPin_, uint8_t buttonPin_, uint32_t flashOff, uint32_t flashOn)
  {
    relayPin = relayPin_;
    buttonPin = buttonPin_;
    flash[Off] = flashOff;
    flash[On] = flashOn;
    pinMode (relayPin, OUTPUT);
    pinMode (buttonPin, INPUT_PULLUP);
    debounceInterval = 20;
  }
  void run(uint32_t currentMillis)
  {
    if (currentMillis - debounceNow >= debounceInterval)
    {
      
      debounceNow = currentMillis;
      uint8_t stateNew = digitalRead(buttonPin) ? LOW : HIGH;
      if (stateOld != stateNew)
      {
        stateOld = stateNew;
        Serial.println("Button");
        if (stateNew == HIGH) flash_control = flash_control ? LOW : HIGH;
      }
    }
    if (currentMillis - flashNow >= flash[digitalRead(relayPin)] and flash_control)
    {
      flashNow = currentMillis;
      digitalWrite(relayPin, digitalRead(relayPin) ? LOW : HIGH);
    }
  }
} buttonFlashRelays[sizeof(ButtonPins)];
// 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 element = 0;
  for (auto &buttonFlashRelay : buttonFlashRelays)
  {
    buttonFlashRelay.make(RelayPins[element], ButtonPins[element],  Flashes [element][Off], Flashes [element][On]);
    element++;
  }
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  uint32_t currentMillis = millis();
  heartBeat(LED_BUILTIN, currentMillis);
  for (auto &buttonFlashRelay : buttonFlashRelays) buttonFlashRelay.run(currentMillis);
}

Ich wünsche Ihnen einen schönen Abend und viel Spaß beim Programmieren in C++.

interessant wurde als SPAM gesehen.
OK wie auch immer

Noch mehr Spaß macht das C++-Programmieren wenn du in dem Beispielcode mit selbsterklärenden Namen drei Taster-Timer-Relais hinzufügen würdest, damit man aus den drei Beispielen das Muster erkennen kann wie die Eintragungen gemacht werden.

Ich bin der Meinung, dass damit der Lerneffekt in der Praxis größer ist.
Je nachdem ob man die Latte zu hoch hängt oder halbwegs passend wird sich ein Anfänger wirklich damit auseinandersetzen oder eben nicht.

@paulpaulson :
was meinst du:
auf einer Skala für Programmierkenntnise die von 1 bis 10 geht
wo befindet sich ungefähr user @manu2796 ?

@manu2796

was für einen Microcontroller benutzt du?

Arduino Uno?, Nano Mega oder noch was anderes?

Auf welche IO-pins sollen die ein/aus-Buttons angeschlossen werden?

Der Sketch soll einige Tasten einer Tastatur in bestimmten Intervall aktivieren.

Versuche es grade mit einem Uno, habe aber auch noch ein Mega zur Verfügung.
Die Pin Belegung ist mir egal.

Bin seit 3 stunden am rumprobieren mit deinen Sketch.
Bis jetzt hat nichts funktioniert.
Ich brauche wohl erst noch bisschen Basis Wissen.

So jetzt habe ich einen Code stehen der arrays benutzt.
Und auf WOKWI mit einem Button und LED gestestet wurde

Für dich als kleine Analyseaufgabe:
In welcher Zeile werden die IO-pins für die Buttons festgelegt?

#include <MobaTools.h>
  
//              Relais Nr  0,  1, 2, 3, 4,  5,  6, 7, 8
const byte relaisPin[] = {254, 2, 3, 4, 10, 11, 7, 8, 9};


//               button Nr 0   1, 2, 3,  4,  5,  6,  7,  8
const byte buttonPin[] = {254, 5, 6, 12, A0, A1, A2, A3, A4};


//            Relais Nr   0,     1,     2,     3,     4,     5,     6,     7,     8
boolean blinkenAktiv[] = {false, false, false, false, false, false, false, false, false};

byte lastButtonState[9];


//                Relais Nr     0,    1,     2,     3,     4,     5,     6,     7,    8
const unsigned long onZeit[] = {0,    400,   400,   400,   400,   400,   400,   400,     0};

//                Relais Nr      0,   1,     2,    3,     4,     5,      6,     7,    8
const unsigned long offZeit[] = {0,  5000, 10000, 176600, 209600, 160000,   800,   800,     0};

const byte debounceTime = 50;
const uint16_t pressTime = 1000;
const byte NoOfButtons = 9;
//MoToButtons myButtons( buttonPin, uint8_t debTime, uint16_t pressTime );

MoToButtons myButtons(buttonPin,NoOfButtons,debounceTime,pressTime); 

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");

  for (byte IndexNr = 1; IndexNr <= 8; IndexNr++) {
    Serial.print("Setze IO-Pin Nr:");
    Serial.print(relaisPin[IndexNr]);
    Serial.println(" als OUTPUT");
    pinMode(relaisPin[IndexNr], OUTPUT);
  }
}


void buttonsAbfragenAnAusSchalten() {
  for (byte IndexNr = 1; IndexNr <= 8; IndexNr++) {
    // prüfe ob ein button gedrückt wurde
    if (myButtons.pressed(IndexNr) == true) {
      Serial.print("myButtons.pressed(");
      Serial.print(IndexNr);
      Serial.println(")");
      // wenn button gedrückt wurde
      // invertiere den Zustand der An-Aus-Variable
      blinkenAktiv[IndexNr] = !blinkenAktiv[IndexNr];
      Serial.print("blinkenAktiv[");
      Serial.print(IndexNr);
      Serial.print("]=");
      Serial.println(blinkenAktiv[IndexNr]);
    }
  }
}


void loop() {
  myButtons.processButtons(); // muss regelmäßig = ca. 100 mal pro Sekunde aufgerufen werden.

  buttonsAbfragenAnAusSchalten();

  for (byte IndexNr = 1; IndexNr <= 8; IndexNr++) {
    if (blinkenAktiv[IndexNr] == true) {
      //delay(1);
      digitalWrite(relaisPin[IndexNr], (millis() % (onZeit[IndexNr] + offZeit[IndexNr])) < onZeit[IndexNr]);
    }
  }
}

Hier die entsprechende WOKWI-Simuation

vgs

Mag sein...

/**
 * 8 Taster, gegen GND geschaltet
 * also invers funktionierend
 * 
 * 8 Relais auf einer der China üblichen Relaiskarte
 * ebenfalls invers schaltend
 * 
 * Die Entprellzeit von 20ms ist in CombieTimer als default 
 * vorgegeben. 
 * 
 * Funktion:
 * Jeder Tastendruck toggelt den Schaltzustand des zugehörigen Relais.
 */

#include <CombiePin.h>
#include <CombieTimer.h>
#include <CombieTools.h>
#include <CombieTypeMangling.h>

using namespace Combie::Millis;




class Task // Interface
{
  public:
  virtual void init() = 0;
  virtual void run()  = 0;
};

template<byte inPin,byte outPin,unsigned long onZeit,unsigned long offZeit>
class Taster2Relais: public Task
{
  private:
  Combie::Pin::TasterGND<inPin>    taster;
  Combie::Pin::RelaisINV<outPin>   relais;
  Combie::Timer::EntprellTimer     entpreller;
  Combie::Tools::FlankenErkennung  flankenerkennung;
  Combie::Timer::PpmGenerator      generator{onZeit,offZeit};
  bool status {false};

  public:
  virtual void init()
  {
    taster.initPullup();
    relais.init();
  }

  virtual void run()
  {
    if(flankenerkennung = entpreller = taster) status = !status;
    relais = status && generator;
  }
};


Task * tasks[] = { 
                   new Taster2Relais<2,10,0.4_Sekunden,1_Sekunde>(), 
                   new Taster2Relais<3,11,0.4_Sekunden,3_Sekunden>(), 
                   new Taster2Relais<4,12,0.4_Sekunden,1_Sekunde>(), 
                   new Taster2Relais<5,13,0.4_Sekunden,1_Sekunde>(), 
                   new Taster2Relais<6,A0,0.4_Sekunden,1_Sekunde>(), 
                   new Taster2Relais<7,A1,0.4_Sekunden,1_Sekunde>(), 
                   new Taster2Relais<8,A2,0.4_Sekunden,1_Sekunde>(), 
                   new Taster2Relais<9,A3,0.4_Sekunden,1_Sekunde>(), 
                 };

               
void setup() 
{
  for(Task * i:tasks) i->init();
}

void loop() 
{ 
  for(Task * i:tasks) i->run();
}

Die Ausdauer ist löblich- Trotzdem meine Empfehlung wäre
10 Minuten probieren und den Sketch anpassen. Wenn es dann nicht läuft oder etwas unklar ist
den veränderten Sketch als ganzes posten
Das Programmverhalten beschreiben
das gewünschte Programmverhalten beschreiben
eine vermutende Frage stellen

Dann werden Sie geholfen

Oft ist es sinnvoll sich nicht unbedingt und sofort ein Problem zu lösen zu wollen.
Ein bißchen zeitlicher Abstand läßt fehler oft viel schneller finden.
Einfach mal darüber schlafen.

Grüße Uwe