Instanz als Parameter übergeben klappt in ArduinoIDE aber nicht in VSC

Hallo zusammen,
in folgendem sketch übergebe ich Klassen Instanzen per Referenz an die Funktionen BlindManualOverride und BlindMovement, sodass die Klassen Member auch direkt durch die Funktion geändert werden können. In der Arduino IDE wird der sketch Fehlerfrei kompiliert und beim Testen funktioniert auch alles wie ich es erhofft habe.

// ########## PIN NUMBERS ##########
// INPUTS
// DIGITAL
int button1 = 2;
int button2 = 3;
int button3 = 4;
int button4 = 5;
int button5 = 6;
int button6 = 7;
int button7 = 8;
int button8 = 9;
// ANALOG
int brightness = 0;
int wind = 1;

// OUTPUTS
int ledRed = 22;
int ledGreen = 23;
int ledYellow = 24;
int ledBlue = 25;
int ledWhite = 26;
// ########## END PIN NUMBERS ##########

// ########## CONSTANCES ##########
// EEPROM ADRESSES - Blinds 25 Bytes, Running Time 10 Bytes
const int eepromBlind1 = 0;
const int eepromRT1 = 25;
const int eepromBlind2 = 35;
const int eepromRT2 = 60;
// ########## END CONSTANCES ##########

// ########## INCLUDES ##########
#include <MikeysBlinds.h>
MikeysBlinds blind1(eepromBlind1);
MikeysBlinds blind2(eepromBlind2);

#include <MikeysRunningTime.h>
MikeysRunningTime rt1(eepromRT1);
MikeysRunningTime rt2(eepromRT2);

#include <MikeysButton.h>
MikeysButton btn1;
MikeysButton btn2;
MikeysButton btn3;
MikeysButton btn4;
MikeysButton btn5;
MikeysButton btn6;
MikeysButton btn7;
MikeysButton btn8;

#include<RTClib.h>
RTC_DS3231 rtc;

#include <MikeysTimer.h>
PulseTimer pulse1sec;

#include <Timezone.h>
TimeChangeRule myDST = {"UTC", Last, Sun, Mar, 3, +60};
TimeChangeRule mySTD = {"UTC", Last, Sun, Oct, 3, +0};
Timezone myTZ(myDST, mySTD);
TimeChangeRule *tcr;
// ########## END INCLUDES ##########

// ########## VARIABLES ##########
bool blind1ManualDownLock, blind1ManualUpLock, blind1ManualDown, blind1ManualUp;
bool blind2ManualDownLock, blind2ManualUpLock, blind2ManualDown, blind2ManualUp;
// ########## END VARIABLED ##########

void setup() {
  Serial.begin(115200);

  // PIN ASSIGNMENTS
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);
  pinMode(button5, INPUT);
  pinMode(button6, INPUT);
  pinMode(button7, INPUT);
  pinMode(button8, INPUT);

  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledYellow, OUTPUT);
  pinMode(ledBlue, OUTPUT);
  pinMode(ledWhite, OUTPUT);
}

void loop() {
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  DateTime rtcnow = rtc.now();

  // AUTO ADJUST DST
  setTime(rtcnow.hour(), rtcnow.minute(), rtcnow.second(), rtcnow.day(), rtcnow.month(), rtcnow.year());
  time_t nowTime, utc;
  utc = now();
  nowTime = myTZ.toLocal(utc);

  blind1.actTime(hour(nowTime), minute(nowTime));
  blind1.actWind(analogRead(wind));
  blind1.actBrightness(analogRead(brightness));
  blind2.actTime(hour(nowTime), minute(nowTime));
  blind2.actWind(analogRead(wind));
  blind2.actBrightness(analogRead(brightness));

  BlindManualOverride(rt1, btn5, btn6, blind1, blind1ManualDownLock, blind1ManualUpLock, blind1ManualDown, blind1ManualUp);
  BlindMovement(rt1, blind1, ledRed, ledGreen, blind1ManualDownLock, blind1ManualUpLock, blind1ManualDown, blind1ManualUp);
  BlindManualOverride(rt2, btn7, btn8, blind2, blind2ManualDownLock, blind2ManualUpLock, blind2ManualDown, blind2ManualUp);
  BlindMovement(rt2, blind2, ledYellow, ledBlue, blind2ManualDownLock, blind2ManualUpLock, blind2ManualDown, blind2ManualUp);
}
// -------------------------------------------------------------------------------------------------- V zB Hier
void BlindManualOverride(MikeysRunningTime rt, MikeysButton btnUp, MikeysButton btnDown, MikeysBlinds &blind, bool &manDownLock, bool &manUpLock, bool &manDown, bool &manUp) {
  if (!rt.referencingNeeded()) {
    if ((manDownLock || manUpLock) && (btnDown.risingEdge() || btnUp.risingEdge())) {
      manDownLock = false;
      manUpLock = false;
    } else if (btnDown.risingEdge() && !btnUp.risingEdge() && !manUpLock) {
      blind.autoMode = false;
      manDown = true;
      manUp = false;
      manUpLock = false;
      manDownLock = true;
    } else if (btnUp.risingEdge() && !btnDown.risingEdge() && !manDownLock) {
      blind.autoMode = false;
      manDown = false;
      manUp = true;
      manUpLock = true;
      manDownLock = false;
    } else if (btnUp.pressed() && btnDown.pressed() && blind.valuesSet()) {
      manDown = false;
      manUp = false;
      manDownLock = false;
      manUpLock = false;
      blind.autoMode = true;
    } else {
      manDown = false;
      manUp = false;
    }

    if (btnDown.held()) {
      manDown = true;
      manUp = false;
      manDownLock = false;
    }
    if (btnUp.held()) {
      manDown = false;
      manUp = true;
      manUpLock = false;
    }
  } else {
    if (btnUp.pressed()) {
      manUp = true;
      manDown = false;
    } else if (btnDown.pressed()) {
      manDown = true;
      manUp = false;
    } else {
      manUp = false;
      manDown = false;
    }
  }
}
// ----------------------------------V zb Hier
void BlindMovement(MikeysRunningTime &rt, MikeysBlinds blind, int pinUp, int pinDown, bool &manDownLock, bool &manUpLock, bool &manDown, bool &manUp) {
  if (((rt.actPositionPercentage() > 0.0) && (rt.actPositionPercentage() < 100.0)) || !rt.valuesSet() || rt.referencingNeeded()) {
    if (blind.move() == 2) {
      digitalWrite(pinUp, HIGH);
      digitalWrite(pinDown, LOW);
      rt.negativeMovement();
    } else if (manDownLock || manDown || (blind.move() == 1)) {
      digitalWrite(pinDown, HIGH);
      digitalWrite(pinUp, LOW);
      rt.positiveMovement();
    } else if (manUpLock || manUp) {
      digitalWrite(pinUp, HIGH);
      digitalWrite(pinDown, LOW);
      rt.negativeMovement();
    } else {
      digitalWrite(pinUp, LOW);
      digitalWrite(pinDown, LOW);
      rt.stopMovement();
    }
  } else if (rt.actPositionPercentage() >= 100.0) {
    if (blind.move() == 2) {
      digitalWrite(pinUp, HIGH);
      digitalWrite(pinDown, LOW);
      rt.negativeMovement();
    } else if (manUpLock || manUp) {
      digitalWrite(pinUp, HIGH);
      digitalWrite(pinDown, LOW);
      rt.negativeMovement();
    } else {
      digitalWrite(pinUp, LOW);
      digitalWrite(pinDown, LOW);
      rt.stopMovement();
    }
    manDownLock = false;
    manDown = false;
  } else if (rt.actPositionPercentage() <= 0.0) {
    if (manDownLock || manDown || (blind.move() == 1)) {
      digitalWrite(pinDown, HIGH);
      digitalWrite(pinUp, LOW);
      rt.positiveMovement();
    } else {
      digitalWrite(pinUp, LOW);
      digitalWrite(pinDown, LOW);
      rt.stopMovement();
    }
    manUpLock = false;
    manUp = false;
  }
}

Der Sketch stellt quasi ein Teilprogramm eines größeren Programms dar (Haussteuerung) Ich versuche gerade diesen Sketch mit Visual Studio Code mit der Arduino Extension in das gesamt Programm einzubauen. Das Programm ist in mehrere einzelne ino-Dateien zerlegt:
Steuerung.ino, a_presetup.ino, b_setup.ino, c_loop1,... m_functions1,...

Beim kompilieren bekomme ich dann Fehlermeldungen wie zb:

n_functions_blinds:9:26: error: variable or field 'BlindManualOverride' declared void
 void BlindManualOverride(MikeysRunningTime rt, MikeysButton btnUp,
                          ^~~~~~~~~~~~~~~~~
n_functions_blinds:9:26: error: 'MikeysRunningTime' was not declared in this scope
d:\xxxxx\Eigene Dateien\Arduino\sketches\Haussteuerung\n_functions_blinds.ino:9:26: note: suggested alternative: MikeysRunningTime_h'

Wenn ich jetzt MikeysRunningTime in MikeysRunningTime_h umbenenne kommt folgendes:

d:\xxxxx\Eigene Dateien\Arduino\sketches\Haussteuerung\g_blinds.ino: In function 'void loop()':
g_blinds:119:1: error: 'BlindManualOverride' was not declared in this scope
 BlindManualOverride(RTblind1, blind1upBtn, blind1downBtn, blind1, blind1ManualDownLock, blind1ManualUpLock, blind1ManualDown, blind1ManualUp);
 ^~~~~~~~~~~~~~~~~~~
d:\xxxxx\Eigene Dateien\Arduino\sketches\Haussteuerung\n_functions_blinds.ino: At global scope:
n_functions_blinds:9:46: error: variable or field 'BlindManualOverride' declared void
 void BlindManualOverride(MikeysRunningTime_h rt, MikeysButton_h btnUp,
                                              ^~
n_functions_blinds:9:46: error: 'rt' was not declared in this scope

Ich versteh das Problem nicht ganz, in der Arduino IDE funktioniert es, in VSC ist ja eigentlich nichts anders, außer das das Programm auf mehrere dateien aufgeteilt wurde.

Ich hoffe ihr versteht mein Problem und könnt mir weiterhelfen, ich danke euch schon mal für eure Zeit :wink:

Bin drauf gekommen: Es war einfach notwendig die Funktion vor dem Setup-Scope zu definieren durch:
BlindManualOverride(MikeysRunningTime rt, MikeysButton btnUp, MikeysButton btnDown, MikeysBlinds &blind, bool &manDownLock, bool &manUpLock, bool &manDown, bool &manUp);

Gut erkannt! Die Arduino IDE macht verschiedene Dinge hinter den Kulissen, die ein normaler (normgerechter) C Compiler nicht macht. Dazu gehören die Deklarationen, die automatisch am Anfang eines Sketch eingefügt werden. Hinzu kommen die Standard Header Dateien, die auch automatisch eingebunden werden, und main.c (oder .cpp?).

Man lernt jeden Tag was neues :wink:
Die anderen Funktionen, die keine Instanz als Parameter benötigen, muss ich allerdings nicht vor dem Programm deklarieren, die funktionieren auch so

Im Arduino Build Ordner zeigt es dir die zusammengeklöppelte *.cpp Datei.
Dort drin findest du auch die automatisch erstellten Prototypen.
Leider klappt das nicht immer so wie man sich das wünscht, mit den automatischen Prototypen.

Im Grunde gilt hier auch die C und C++ typische Regel, alles muss wenigstens deklariert sein, bevor es verwendet werden darf.
Wo dann die Definition zu finden ist, ist zweitrangig.
Eher ein Problem des Linkers.
Dem fällt das dann auf, wenn er etwas nicht auflösen kann.

Danke für die Erklärung :wink: