mehrere Instanzen einer Funktion erzeugen/aufrufen

Es geht um eine eigentlich recht simple Rollosteuerung.
Ich hab mir dazu eine Funktion gebaut die an sich so funktioniert.
Das Problem ist jetzt das ich 12 Rollos habe die ich mit der selben Funktion steuern will.

Ich bekomme es nicht hin die Funktion so aufzurufen das es richtige Instanzen werden die sich nicht beeinflussen oder überschneiden.
So wie es aktuell ist funktioniert das leider nicht:

const int buttonAuf[] = {4, 8};
const int buttonAb[] = {5, 9};

const int relaisAuf[] =  {6, 10};
const int relaisAb[] =  {7, 11};

const int led =  13;

const int rolloIndex =  2;

int rolloArray[rolloIndex];
int rollo[rolloIndex];

int schritt;
int index;

bool statusRelaisAuf;
bool statusRelaisAb;
bool autoRelaisAuf;
bool autoRelaisAb;
bool neustartErlaubt;

bool ButtonAufEDGEPOS;
bool ButtonAbEDGEPOS;

int statusButtonAuf[rolloIndex];
int statusButtonAb[rolloIndex];
bool statusButtonAufAlt;
bool statusButtonAbAlt;

unsigned long buttonGedrueckZeit;
unsigned long autoRelaisStartZeit;
unsigned long rolloAbZeit;
unsigned long rolloAufZeit;
unsigned long neustartZeit;
unsigned long StartZeitButtonAuf;
unsigned long StartZeitButtonAb;
unsigned long StartZeitAutoRelais;

unsigned long previousMillis = 0;   // will store last time LED was updated
unsigned long ZeitseitStart = 0;
unsigned long StartZeit = 0;
const long interval = 50;

void setup() {
  // put your setup code here, to run once:
  for (index=0; index <= 1; index++){
    digitalWrite(relaisAuf[index], HIGH);
    digitalWrite(relaisAb[index], HIGH);
    pinMode(relaisAuf[index], OUTPUT);
    pinMode(relaisAb[index], OUTPUT);
    pinMode(buttonAuf[index], INPUT_PULLUP);
    pinMode(buttonAb[index], INPUT_PULLUP);
  }

  pinMode(led, OUTPUT);

  neustartErlaubt = HIGH;

  Serial.begin(9600);

  autoRelaisStartZeit = 500;
  rolloAbZeit = 5000;
  rolloAufZeit = 5000;
  StartZeit = 0;
  autoRelaisAuf = LOW;
  autoRelaisAb = LOW;

}

void loop(){

statusButtonAuf[0] = digitalRead(buttonAuf[0]);
statusButtonAb[0] = digitalRead(buttonAb[0]);
statusButtonAuf[1] = digitalRead(buttonAuf[1]);
statusButtonAb[1] = digitalRead(buttonAb[1]);



for (index=0; index <= 1; index++){
  rollo[index] = {rolloFunktion(index, rollo[index], statusButtonAuf[index], statusButtonAb[index], autoRelaisStartZeit, rolloAbZeit, rolloAufZeit)};
}



  Serial.print(statusButtonAuf[0]);
  Serial.print(statusButtonAb[0]);
  Serial.print(" ");
  Serial.print(statusButtonAuf[1]);
  Serial.print(statusButtonAb[1]);
  Serial.print(" ");
  Serial.print( rollo[0]);
  Serial.print(" ");
  Serial.print( rollo[1]);
  Serial.print(" ");
  Serial.println( index);

}

int rolloFunktion(int index, int schritt, int ButtonAuf, int ButtonAb, unsigned long autoRelaisStartZeit, unsigned long rolloAbZeit, unsigned long rolloAufZeit) {

  unsigned long currentMillis = millis();

  if (neustartErlaubt == LOW) {
    digitalWrite(led, HIGH);
    digitalWrite(relaisAuf[index], HIGH);
    digitalWrite(relaisAb[index], HIGH);
    StartZeit = 0;
    if ((neustartZeit + 2000) <= currentMillis) {
      digitalWrite(led, LOW);
      neustartErlaubt = HIGH;
    }
  }  

  switch (schritt) {
    case 0: //Warte bis Starten wieder freigegeben ist
      if (neustartErlaubt == HIGH) {
        Serial.println("neustart erlaubt");
        schritt = 1;
      }
      break;
    case 1:
      if (ButtonAuf == LOW) {
        Serial.println("buttonAuf");
        StartZeitButtonAuf = currentMillis;
        schritt = 10;
      }
      else if (ButtonAb == LOW) {
        Serial.println("buttonAb");
        StartZeitButtonAb = currentMillis;
        schritt = 50;
      }
      break;
    case 10:
      if (ButtonAuf == LOW) {
        Serial.println("relais einschalten");
        digitalWrite(relaisAuf[index], LOW);
        schritt = 15;
      }
      else {
        neustartZeit = currentMillis;
        neustartErlaubt = LOW;
        schritt = 0;
      }
      break;
    case 15:
      if (ButtonAuf == LOW) {
        if ((StartZeitButtonAuf + autoRelaisStartZeit) <= currentMillis) {
          Serial.println("autorelais ein");
          buttonGedrueckZeit = currentMillis;
          autoRelaisAuf = HIGH;
          StartZeitAutoRelais = currentMillis;
          schritt = 20;
        }
      }
      else if (ButtonAuf == HIGH) {
        Serial.println("button aus");
        digitalWrite(relaisAuf[index], HIGH);
        neustartZeit = currentMillis;
        neustartErlaubt = LOW;
        schritt = 0;
      }
      break;
    case 20:
      if (autoRelaisAuf == HIGH && ((StartZeitAutoRelais + rolloAufZeit)) <= currentMillis) {
        if (ButtonAuf == HIGH) {
          Serial.println("autorelais ende");
          autoRelaisAuf = LOW;
          digitalWrite(relaisAuf[index], HIGH);
          StartZeit = 0;
          schritt = 25;
        }
      }
      else if (ButtonAb == LOW){
        Serial.println("autorelais abbruch durch taster");
        autoRelaisAuf = LOW;
        digitalWrite(relaisAuf[index], HIGH);
        StartZeit = 0;
        schritt = 25;
      }
      break;
    case 25:
      Serial.println("ende");
      neustartZeit = currentMillis;
      neustartErlaubt = LOW;
      schritt = 0;
      break;
    case 50:
      if (ButtonAb == LOW) {
        Serial.println("relais einschalten");
        digitalWrite(relaisAb[index], LOW);
        schritt = 55;
      }
      else {
        neustartZeit = currentMillis;
        neustartErlaubt = LOW;
        schritt = 0;
      }
      break;
    case 55:
      if (ButtonAb == LOW) {
        if ((StartZeitButtonAb + autoRelaisStartZeit) <= currentMillis) {
          Serial.println("autorelais ein");
          buttonGedrueckZeit = currentMillis;
          autoRelaisAb = HIGH;
          StartZeitAutoRelais = currentMillis;
          schritt = 60;
        }
      }
      else if (ButtonAb == HIGH) {
        Serial.println("button aus");
        digitalWrite(relaisAb[index], HIGH);
        neustartZeit = currentMillis;
        neustartErlaubt = LOW;
        schritt = 0;
      }
      break;
    case 60:
      if (autoRelaisAb == HIGH && ((StartZeitAutoRelais + rolloAbZeit)) <= currentMillis) {
        if (ButtonAb == HIGH) {
          Serial.println("autorelais ende");
          autoRelaisAb = LOW;
          digitalWrite(relaisAb[index], HIGH);
          StartZeit = 0;
          schritt = 65;
        }
      }
      else if (ButtonAuf == LOW){
        Serial.println("autorelais abbruch durch taster");
        autoRelaisAb = LOW;
        digitalWrite(relaisAb[index], HIGH);
        StartZeit = 0;
        schritt = 65;
      }
      break;
    case 65:
      Serial.println("ende");
      neustartZeit = currentMillis;
      neustartErlaubt = LOW;
      schritt = 0;
      break;
  }
  return schritt;
}

bist du sicher, dass du das willst?

const int rolloIndex = 2;

int statusButtonAuf[rolloIndex];
int statusButtonAb[rolloIndex];

Du meinst: eine Funktion mit einem Parameter aufrufen, der zwischen den verschiedenen Rollos unterscheidet.
Damit du nicht alles doppelt (bei zwei Rollos) aufschreiben musst.

Der Name Rolloindex ist etwas verwirrend. Im üblichen Sprachgebrauch nennt man das

const int RolloAnzahl=2;

Damit kannst du Arrays erzeugen.

const byte buttonAb[RolloAnzahl] = {5, 9};
Wenn du dann einen deiner Rollos meinst, nennst du die Variable die den einzelnen Rollo bezeichnet: index
und Funktionen nehmen gern einen Aufrufparameter:

void rolloSteuerung(int index) {
  bool abStatus = digitalRead(buttonAb[index]);
  ...
}

void loop () {
  for (int i = 0; i < RolloAnzahl; i++) rolloSteuerung(i);  // wird hier zwei mal (mit 0 und 1) aufgerufen
}

Ich bekomme es nicht hin die Funktion so aufzurufen das es richtige Instanzen werden die sich nicht beeinflussen oder überschneiden.
So wie es aktuell ist funktioniert das leider nicht:

Der Erste Schritt wäre, alle Daten, welche zu EINEM Rollo gehören in einer Struktur zusammen zu fassen.
Und Zack, kann man diese Strukturen in einem Array verwalten.

Diese Struktur könnte man dann mit Funktionen versehen.
Und dann wäre man schon bei richtigen Klassen/Instanzen.
Mit beiden Beinen in der OOP

Ich habe den Sketch nur kurz überflogen... aber ich vermute mal schwer, dass jedes der 12 Rollos separat gesteuert werden soll?! So rein "spontan" fällt mir dazu ein dass es für so etwas sogar zwei gute Möglichkeiten gibt.

Erstens: Du erstellt dir ein "struct", bei dem du die einzenen Komponenten für ein einzelnes Rollo per Namen ansprechen / abrufen kannst. Aus dem "struct" machst du ein Array und fertig. Somit brauchst du nur eine einzige Steuerfunktion schreiben der du lediglich den Index des Rollos übergibst. Alles darin enthaltene arbeitet dann unabhängig und behakt sich nicht gegenseitig.

Zweitens: Ich selbst würde das ganze in ein "Class" gießen. Dann kannst du wirklich deine "Instanzen" je Rollo anlegen und kannst alles parallel betreiben, ohne dass ein Rollo mit einem anderen ins Gehege kommt. Die "Hürde" dazu ist für einen kurzen Moment vielleicht hoch. Aber einmal im Griff, eröffnen sich dadurch die besten Lösungsmöglichkeiten.

Is nur so 'n Gedankengang...

PS:
Cool, passt doch zu combie's Vorschlag
Er war mal wieder schneller...

*Nachsatz...
Nützliche Infos zu "structs" findest du hinter folgendem Link, der hier im Forum schon mehrfach aufgeführt worden ist:
http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/015_c_strukturen_001.htm

ardubu:
bist du sicher, dass du das willst?

const int rolloIndex = 2;

int statusButtonAuf[rolloIndex];
int statusButtonAb[rolloIndex];

versteh ich nicht!?

ja das mit den Class zeug hab ich mir schon mal angesehen und wollte den Aufwand eigentlich nicht betreiben, bin schon froh wenn ich mit der Syntax und den basissachen halbwegs klar komme...

danke für den link werde mir das mal reinziehen...

dahofa:
Ich hab mir dazu eine Funktion gebaut die an sich so funktioniert.
...
So wie es aktuell ist funktioniert das leider nicht:

Aha! Du hast also eine Rollosteuerung, die "so funktioniert", aber "So wie es aktuell ist funktioniert das leider nicht"

Finde den Widerspruch in Deinen Aussagen!

Also zumindest scheint es Deinem Code an der freien Skalierbarkeit der Rolloanzahl zu fehlen.

Hast Du Dir schon mal den Rollo-Steuerungs-Sketch angesehen, den ich hier mal im Forum gepostet hatte?

Die Button-Logik (für im Prinzip beliebig viele bzw nur durch die Pin-Anzahl des Arduino-Boards begrenzte Anzahl Rollos) ist dabei:

Up-Button eines Rollos drücken: Rollo läuft hoch, und zwar entweder bis zum Timeout , oder bis der Up-Buttton nochmals oder der Down-Button desselben Rollos gedrückt wird, je nachdem was zuerst eintritt (und hält dann an.

Down-Button eines Rollos drücken: Rollo läuft runter, und zwar entweder bis zum Timeout , oder bis der Down-Buttton nochmals oder der U-Button desselben Rollos gedrückt wird, je nachdem was zuerst eintritt (und hält dann an. Buttons wahlweise mit PullDown- oder PullUp-Widerstand beschaltet. Kennst Du den Sketch hier aus dem Forum?

jurs:
Aha! Du hast also eine Rollosteuerung, die "so funktioniert", aber "So wie es aktuell ist funktioniert das leider nicht"

Finde den Widerspruch in Deinen Aussagen!

nein denn einmal geht es um die Funktion der Funktion und dann darum das ich eben mehrere Instanzen der Funktion nicht hin bekomme. Oder anders: die Rollofunktion für nur ein Rollo (2 Relais 2 Schalter) funktioniert, versuche ich es mit zwei Rollos funktioniert es eben nicht mehr...

jurs:
Also zumindest scheint es Deinem Code an der freien Skalierbarkeit der Rolloanzahl zu fehlen.

und genau das ist es warum ich mich an euch wende, siehe oben.

nein den Sketch kenne ich leider nicht,...

dahofa:
nein denn einmal geht es um die Funktion der Funktion und dann darum das ich eben mehrere Instanzen der Funktion nicht hin bekomme.

Instanzen gibt es nicht von Funktionen, sondern nur von Objekt-Klassen ("class")

Der Vorläufer einer Klasse (class) ist eine Datenstrruktur (struct).
Und die "Instanz" eines struct bezeichnet man eher als Variable denn als Instanz.
Ein struct ist quasi dasselbe wie eine class, nur eben gehören zu einem struct nur eigene Daten/Variablen, aber keine eigenen Funktionen. Obwohl: Der GCC-Compiler sieht das nicht so eng.

Funktionen kannst Du allenfalls rekursiv aufrufen, also dass beispielsweise dieselbe Funktion "sich selbst" nochmal aufruft. Aber damit wirst Du meistens nichts (alte Faustregel "rekursiv geht meistens schief".

Und so wie Du von einer Klasse verschiedene Instanzen anlegen kannst, kannst Du von einem struct ein Array anlegen (array of struct), und dann beispielsweise in einer Funktion ein ganzes array-of-strruct per for-schleife durchlaufen und anstehende Aktionen (z.B. Buttonabfragen, Relaisschaltungen) abarbeiten. Dazu müßtest Du dann aber davon abkommen, nur einen einzigen Satz globaler Variablen für alle Rollos zu haben:

bool statusRelaisAuf;
bool statusRelaisAb;
bool autoRelaisAuf;
bool autoRelaisAb;

sondern Du brauchst eine Datenstruktur (struct), die für jedes Relais diese Variablen bereithält und legst davon ein Array an.

Meinen Rolladen-Beispielsketch findest Du hier

Die Datenstruktur ist dabei im Code definiert in !n !struct roll_t"

Als Array habe ich nur beispielhaft Daten für zwei Rollos deklariert:

roll_t rollladen[]={
  {2,3,false, false, NOACTION,0,60000L, A0, A1}, // Button-Pins 2, 3, Relay-Pins A0, A1, Timeout 60 secons
  {4,5,false, false, NOACTION,0,45000L, A2, A3}, // Button-Pins 4, 5, Relay-Pins A2, A3, Timeout 45 secons
};

Und der Steuerungsfunktion habe ich keinen eigenen Namen gegeben, die heißt einfach "loop()" und die Programmlogik steckt innerhalb der for-Schleife in der loop()-Funktion

Du meinst auch nicht "Instanz", sondern willst eine Funktion mehrfach aufrufen, damit sie einmal Rollo1 und beim zweiten Mal Rollo2 bearbeitet. (So verstee ich jedenfalls dein Verständnis-Problem)

Klar sind struct oder Objekte eleganter, aber wenn es für dich einfacher verständlich ist, kannst du auch mit einem Haufen Arrays arbeiten. Hauptsache, in jedem Array ist der gleiche Index für das gleiche Rollo zuständig.

Das mit dem rekursiv hat jurs nur erwähnt, um dich zu verwirren.

jurs:
Instanzen gibt es nicht von Funktionen,

Das ist nicht ganz korrekt.

Eine (u.U. indirekt aber nicht end-) rekursive Funktion hat durchaus mehrere Instanzen gleichzeitig.

In C++ ist der einzige Unterschied zwischen struct und class dass die Daten eines structs standardmäßig public sind und die einer Klasse private.