Platzhalter für Befehle

Hallo

Ich frage mich, ob es möglich ist, z.B. für die Befehle Serial.read() oder Serial.available() einen Platzhalter anstelle von Serial zu verwenden, der dann mit einer if/else Abfrage durch Serial oder Serial1 ersetzt wird. Es würde bestimmt einiges an Code sparen in manchen Fällen.
Das würde z.B. benötigt, wenn ich an mehreren seriellen Ausgängen schreiben oder lesen möchte und der Sendevorgang resp. Einlesevorgang für alle Ports derselbe sein soll.

Im Prinzip wie wenn ich byte port = 1; definiere, dann hat port den Wert 1 hinterlegt. Gibt es sowas auch für Befehle, dass man z.B. char port = Serial; definieren könnte und dieses dann im Programm zu port = Serial1; wechselt wenn nötig?

Grüsse

Stef

Serial implementiert Stream und so auch Print!
Damit lässt sich einiges anstellen

#include <Streaming.h> // die Lib findest du selber ;-)
//Stream &cout = Serial; // cout Emulation für "Arme"
Stream &cout = Serial1; // cout Emulation für "Arme"

#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() 
{
  Serial1.begin(9600);
  lcd.begin();
  lcd.backlight();
  
  cout << F("Start: ") << F(__FILE__) << endl;

  lcd << "Hallo!"
}

void loop() 
{

}

C/C++ arbeitet nicht mit "Befehlen". Wenn für dich alles ein Befehlt ist verstehst du die Zusammenhänge schwieriger

Für sowas gibt es Zeiger und Referenzen. Wenn du das mitten im Programm ändern willst nimmt man Zeiger. Referenzen kann man nur einmal beim Initialisieren zuweisen.

Man kann das auch für Funktions-Parameter verwenden und jeweils ein anderes Serial Objekt übergeben:

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

  println(Serial, "Test");
  println(Serial, 100);
  println(Serial, 10.5, 2);
}

void loop ()
{  
}

template<typename... Types>
inline void println(Stream& stream, Types... args)
{
  stream.println(args...);
}

Hallo,
wenn es nicht zur Laufzeit , sonder beim Compilieren entschieden wird könnte #define eventuell eine Lösung sein.

#define Printer Serial
// #define Printer Serial1
void setup() {
  // put your setup code here, to run once:
Printer.begin(115200);
Printer.println("Hallo");
}

void loop() {
  // put your main code here, to run repeatedly:

}

Vielen lieben Dank an alle! Das mit den Funktionen und definition über Stream ist super! Genau sowas habe ich gesucht :slight_smile: Manchmal ist es gar nicht so weit weg, man darf nur nicht so weit denken... Vielen Dank nochmals!

Kommt darauf an ob Du es zum Kompilierungszeitpunkt schon weißt welche serielle Schnittstelle Du benutzt oder nicht.

Wenn Du zum Kompilierzeitpunkt weißt dann kannst Du mit "#define" und "#if" "#else" und "#endif" arbeiten, also bedingte Kompilierung.
https://de.wikibooks.org/wiki/C-Programmierung:_Präprozessor

Wenn Du es erst zur Laufzeit weißt dann ist es so wie meine Vorredner.

Grüße Uwe

Zur Kompilierungszeit ist mir klar wie, aber das andere ist mir nicht in den Sinn gekommen. Es geht mir schon um im laufenden Programm zu definieren was wo gesendet resp. empfangen werden soll. Das passt so perfekt :wink:

Oder einfach nur zur Verkürzung des Codes:

#define pt(x) Serial.print(x)
#define ptln(x) Serial.println(x)

void setup(){
  Serial.begin(57600);
  pt("Hallo ");
  ptln("Welt");
  pt(17);
}

Geht aber mit Änderung im laufenden Programm nicht so gut.

Danke! Das ist auch gut, aber für mein eigentliche Frage nicht geeignet. Ich möchte während der Ausführung des Programmcodes die serielle Schnittstelle ändern. Habe auch schon in der Funktion Parameter drin, dann kann ich am einfachsten gleich auch noch mit Stream& den passenden port definieren. Das ist wirklich gut!

#define geht hin und macht quasi nichts anderes als ein "Suchen & Ersetzen" im Code.
Mit dem (x) kann man Platzhalter für Parameter berücksichtigen.
Es hält Dich also nichts davon ab auch Stream zu verwenden und die stream.println() Aufrufe einzukürzen :slight_smile:

geh komm. Das bringt doch nichts. ein define für ein print, eins für println.
Dann noch eins für print mit zwei Parameter und eins mit println für zwei Parameter.
4 defines weil du ihm nicht zeigst wie man __VA_ARGS__ nutzt unter dem Deckmantel zum "Tipparbeit" sparen.

Außerdem will er zur Laufzeit umschalten.
#define
ist auf die Frage des TO eine unpassende Antwort.

#define hat einen wichtigen Anwendungsfall: Debug-Ausgaben mit einer Zeile Ein- und Ausschalten

Darum geht es hier aber nicht. Er will zur Laufzeit umschalten. Also z.B. eine Funktion haben mit der man den gleichen Inhalt auf zwei Schnittstellen ausgeben kann (Einlesen von verschiedenen Quellen ginge genauso).

Den Vorteil sieht man vielleicht wenn man mal längere Ausgaben hat:

void print(Stream& stream, int x, int y, int z)
{
   stream.print("X :"); stream.println(x);
   stream.print("Y :"); stream.println(y);
   stream.print("Z :"); stream.println(z);
}

Stream geht übrigens nicht nur mit Serial. Auch andere Klassen sind davon abgeleitet. Eine Funktion die eine Zeile von der seriellen Schnittstelle einlesen kann, geht auch ohne Änderungen für eine Zeile von einer SD-Karte