SerialEvent reagiert nicht

Hallo Leute ich habe ein Problem!
Ich muss für ein Projekt für die FH zwei Arduino M0 pro per UART miteinander verbinden. Dabei soll Arduino A Befehle an Arduino B senden. Da ich nicht ständig mit Serial.available() auf den UART hören möchte dachte ich mir ich verwende serialEvent(). Leider hat dies nicht funktioniert. Darum habe ich mich näher mit serialEvent() beschäftig. Dazu habe ich das Arduino Beispielprogramm verwendet.

String inputString = "";         // a String to hold incoming data
boolean stringComplete = false;  // whether the string is complete

void setup() {
 // initialize serial:
 Serial.begin(9600);
 // reserve 200 bytes for the inputString:
 inputString.reserve(200);
}

void loop() {
 // print the string when a newline arrives:
 if (stringComplete) {
   Serial.println(inputString);
   // clear the string:
   inputString = "";
   stringComplete = false;
 }
}

/*
 SerialEvent occurs whenever a new data comes in the hardware serial RX. This
 routine is run between each time loop() runs, so using delay inside loop can
 delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
 while (Serial.available()) {
   // get the new byte:
   char inChar = (char)Serial.read();
   // add it to the inputString:
   inputString += inChar;
   // if the incoming character is a newline, set a flag so the main loop can
   // do something about it:
   if (inChar == '\n') {
     stringComplete = true;
   }
 }
}

Dabei bekomme ich aber keine Anzeige im SerialMonitor. Was mache ich da falsch?

PS.: Auf die Boudrate habe ich geachtet

Danke schon mal für die Hilfe
MfG

Nimm bitte die Leerzeichen aus den Code-Tags raus, dann passt es auch mit der Darstellung.

noiasca:
die Frage ist, warum du das nicht machen möchtest.

Ich möchte gerne den Arduino so lange an einer Aufgabe Arbeiten lassen bis am UART ein Befehl anliegt. Das Problem ist das ich(bzw der Arduino) nicht weiß wann ein Befehl am UART reinkommt.
Auf der Seite
http://www.mathias-wilhelm.de/arduino/beginner/schritt-3-den-arduino-steuern/
wird behauptet das es sich bei serialEvent um eine Interruptrutiene handelt.

Ypoolp:
Ich möchte gerne den Arduino so lange an einer Aufgabe Arbeiten lassen bis am UART ein Befehl anliegt. Das Problem ist das ich(bzw der Arduino) nicht weiß wann ein Befehl am UART reinkommt.
Auf der Seite
http://www.mathias-wilhelm.de/arduino/beginner/schritt-3-den-arduino-steuern/
wird behauptet das es sich bei serialEvent um eine Interruptrutiene handelt.

Wenn du das in der Loop laufen lässt, merkt er das doch auch.

Und was ist mit den Code-Tags ?

Ypoolp:
http://www.mathias-wilhelm.de/arduino/beginner/schritt-3-den-arduino-steuern/
wird behauptet das es sich bei serialEvent um eine Interruptrutiene handelt.

Das macht es nicht wahrer.

SerialEvent ist eine Routine, die zwischen den Aufrufen von loop ausgeführt wird.

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}

Serial ist im Vergleich zum Controller sehr langsam. Bei 9600 Baud braucht ein Zeichen 1 / 9600 * 10 Sekunden (10 Bit wegen dem 8N1 Format). Das ist ca. 1 Millisekunde. Da hast du massig Zeit in loop() Dinge zu tun und abzufragen ob Daten vorhanden sind.

Es muss egal sein, ob man das Gedöns in serialEvent() oder in loop() abhandelt.
Eine reine Geschmacksfrage.

Es sei denn, der Arduino Core für diesen Prozessor ist kaputt

serialEvent() wird nur aufgerufen, wenn Daten anliegen.
Quasi Nebenläufig.

Das sollte eigentlich zigtausende von wirkungslosen, damit unnötigen, Serial.available() Aufrufen in loop() einsparen.

Von daher empfinde ich den Geschmack von serialEvent() als gut.

combie:
serialEvent() wird nur aufgerufen, wenn Daten anliegen.
Quasi Nebenläufig.

Das sollte eigentlich zigtausende von wirkungslosen, damit unnötigen, Serial.available() Aufrufen in loop() einsparen.

Es spart sie nicht ein, es verlagert sie nur.

Zusätzlich kommen noch zwei Abfragen auf Pointer dazu und zwei Unterprogrammaufrufe.

Mit if (Serial.available()) { in loop ist man auf alle Fälle schneller (und deutlicher).

void serialEventRun(void)
{
#if defined(HAVE_HWSERIAL0)
  if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
#endif
#if defined(HAVE_HWSERIAL1)
  if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1();
#endif
#if defined(HAVE_HWSERIAL2)
  if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2();
#endif
#if defined(HAVE_HWSERIAL3)
  if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3();
#endif
}

Den Aufruf von serialEventRun hatte ich ja oben schon gepostet.

Du möchtest mir damit sagen, dass serialEventRun() wegoptimiert wird, wenn keine serialEvent() definiert ist?

Das müsste man mal untersuchen...
Daran glauben kann ich noch nicht.

Das wird - soweit ich weiss - durch die weak references erledigt.

// SerialEvent functions are weak, so when the user doesn't define them,
// the linker just sets their address to 0 (which is checked below).
// The Serialx_available is just a wrapper around Serialx.available(),
// but we can refer to it weakly so we don't pull in the entire
// HardwareSerial instance if the user doesn't also refer to it.

Ob das serialEventRun() völlig entfernt, kann ich nicht sagen,
im Allgemeinen überrascht der Optimizer eher positiv als negativ.

serialEventRun() ist aber nicht weak, oder?
Durch die muss es durch, egal ob serialEvent() definiert ist, oder nicht.

Muss ich wirklich mal testen, was "effektiver" ist.

combie:
serialEventRun() ist aber nicht weak, oder?
Durch die muss es durch, egal ob serialEvent() definiert ist, oder nicht.

Doch, ist sie.

HardwareSerial.h:

extern void serialEventRun(void) __attribute__((weak));

main.cpp

	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}

Na, dann …

Nachtrag:
Habe in den generierten Code geschaut.
serialEventRun() wird einkompiliert und aufgerufen.
Auch wenn keine serialEvent() erstellt wurde.

Nachdem das nun endlich geklärt und ausdiskutiert ist (Wer's mit serialEvent übersichtlicher findet, handelt sich nur ein wenig Overhead ein) , bleibt die eigentliche Frage, warum ypoolp's Sketch nicht funktioniert ?

Mir bleibt als Vermutung nachzufragen, ob der SerialMonitor so eingestellt ist, dass er '\n' an eine gesendete Zeile anfügt ? ( "Neue Zeile" oder "Sowohl ..." )
Sonst sehe ich keinen offensichtlichen Fehler im Beispiel-Sketch in #0. Sonst jemand eine Idee?

Serial: 0 (RX) and 1 (TX). Used to receive (RX) and transmit (TX) TTL serial data using the ATSAMD21G18 hardware serial capability. Note that on the M0, the SerialUSB class refers to USB (CDC) communication; for serial on pins 0 and 1, use the Serial5 class.

Für Serial über USB fehlt mir also das

while (!Serial) ;

Für Kommunikation über Pins 0 und 1 wird die falsche Schnittstelle benutzt.

Der gepostete Kode funktioniert ohne Probleme auf einem Nano.

Einen M0 habe ich nicht.

So nun schaffe ich es auch entlich mal wieder online zu kommen.

Vielen Dank schon mal für die vielen Komentare.

  1. Ich werde es jetzt mit Serial.available() versuchen zu realisieren, da es ja wie es aussieht keinen Unterschied dazu macht ob man es mit serialEvent() programmiert (auser ein bischen Overhead).

  2. Ich habe mein Programm dann auch noch zur Kontrolle auf eine Arduino UNO getestet aber hier klappt es auch nicht.
    Kann es auch sein das es mit dem Mikrocontroler zusammenhängt weil er kein AVR-Kontoller ist?
    Der Dateipfad in dem ich gesucht habe lautet nämlich:
    C:...\hardware\arduino\avr\cores\arduino
    Aber ich habe ja keine AVR. Die Frage die sich mir dann stellt wo liegt das Zeug für die ARM Kontroller?

Für Kommunikation über Pins 0 und 1 wird die falsche Schnittstelle benutzt.

Das verstehe ich nicht ganz. müsste ich dann z.B Serial5.available() schreiben um etwas über die Pins 0 und 1 zu senden?

auf eine Arduino UNO getestet aber hier klappt es auch nicht.
....
Aber ich habe ja keine AVR.

Da sehe ich einen Widerspruch!

Und nein, ich weiß nicht ob das auf deinem M0 funktioniert.
Weiß aber, dass serialEvent() auf dem Uno, ESP und Mega prächtig funktionieren, da ich dieses selber gerne einsetze.

Ypoolp:
Das verstehe ich nicht ganz. müsste ich dann z.B Serial5.available() schreiben um etwas über die Pins 0 und 1 zu senden?

Nö, senden kannst du mit .available() nicht, checken ob etwas empfangen wurde schon.

Ansonsten sollte laut der Dokumentation Serial5 für die Pins 0 und 1 verwendet werden.