String seriell empfangen

Hi Leute,

ich habe folgendes Problematik:
Das erste programm wird einfach nur zeigen wie ich daten von einem Uno versende, welche dem entsprechen die ich von dem später angeschlossenen Gerät erwarte.

Mit dem zweiten möcht ich an einem Mega diese als string empfangenund später noch weiter verarbeiten (dazu an dieser Stelle aber nichts).

Mein Problem ist jetzt das zwar der korrekte String dargestellt wird aber das ganze mehrmals hintereinander. ca 5-6mal ... oder öfter.

Wie kann ich dies verhindern? Ich möchte den quasi auch ersteinmal korrekt und einzeln empfangen. Falls die Frage auftaucht warum ich diesen überhaupt 1 zu 1 weitersende.. ich möchte diesen einfach am Messgerät analysieren können.

Hier der Code 1 (senden des erwarteteten Signals):

char Acht = 56;
char Start = 2;
char D = 68;
char F = 70;
char ETX = 3;
char CR = 13;
char C = 67;
char Null = 48;
char Drei = 51;
char M = 77;
char P = 80;
char S = 83;
char A = 65;
char Semi = 59;
char Eins = 49;
char Zwei = 50;
char R = 82;
char Sieben = 55;
char Fuenf = 53;
char T = 84;



void setup(){
  Serial.begin(4800);
}
void loop()
{
  Serial.print(Start);
  Serial.print(S);
  Serial.print(Eins);
  Serial.print(Semi);
  Serial.print(A);
  Serial.print(Semi);
  Serial.print(C);
  Serial.print(Null);
  Serial.print(Drei);
  Serial.print(Semi);
  Serial.print(M);
  Serial.print(Null);
  Serial.print(Drei);
  Serial.print(M);
  Serial.print(Null);
  Serial.print(Null);
  Serial.print(Semi);
  Serial.print(P);
  Serial.print(Eins);
  Serial.print(Zwei);
  Serial.print(Null);
  Serial.print(Acht);
  Serial.print(Null);
  Serial.print(Eins);
  Serial.print(Null);
  Serial.print(Null);
  Serial.print(Null);
  Serial.print(Null);
  Serial.print(Semi);
  Serial.print(R);
  Serial.print(Null);
  Serial.print(Sieben);
  Serial.print(Fuenf);
  Serial.print(Semi);
  Serial.print(T);
  Serial.print(Null);
  Serial.print(Fuenf);
  Serial.print(Semi);
  Serial.print(Semi);
  Serial.print(D);
  Serial.print(Zwei);
  Serial.print(Semi);
  Serial.print(ETX);
  Serial.print(CR);
  
  
  

  
  delay(5000);
}

Jetzt der zweite zum empfangen:

String str;

void setup(){
  Serial.begin(4800);
  Serial1.begin(4800);
}

void loop() 
{
    if(Serial.available() > 0)
    {
        str = Serial.readStringUntil('\n');
        
        delay(5000);
    }
    
    
    
    Serial1.print(str);
    
    
    
    
}

Ich hätte gerne noch die Bilder vom Analyzer eingefügt.. aber das bekomm ich gerade nicht hin.. (wie geht das (.png)).

Dort ist auf jedenfall zu erkennen das das gesendete Signal kommt. Die Antwort verzögert sich und ist dann durchgehend solange bis ungefähr das nächste \n kommt.

Wie kann ich verhindern das die Ausgabe mehrfach ist?

Vielen dank im vorraus

Vernünftiger einlesen geht so:

const int SERIAL_BUFFER_SIZE = 81;
char serialBuffer[SERIAL_BUFFER_SIZE];

void loop()
{
   if(readSerial())
       processSerial();
}

bool readSerial()
{
	static unsigned int index;

	if(Serial.available() > 0)
	{		
		char c = Serial.read();
		
	        if(c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
		{
			serialBuffer[index++] = c;
		}
                else if(c == '\n')
		{
			serialBuffer[index] = '\0';
			index = 0;
			return true;
		}
	}
	return false;
}

void processSerial()
{
     Serial1.print(serialBuffer);
}

readSerial() schaut ständig nach ob was im Eingangspuffer ist und wenn ja lies das Zeichen ein und schreibt es ins Array. Wenn das Linefeed angekommen ist, gibt die Funktion true zurück.

processSerial() scheint hier erst mal Overkill, aber wenn du mit dem String dann was kompliziertes machen willst, ist es so besser.

Dieser Code erfordert zwingend ein abschließendes Endzeichen! Hier ein Linefeed. Du musst als am Ende ein '\n' senden, oder am Ende println() machen. Andere Steuerzeichen wie CR sind auch denkbar.
In deinem Sende-Code sehe ich da kein LF. Was du aber ebenfalls erwartest. Kann sein es dass es deswegen nicht geht.

Und auf der Sendeseite kannst du sowas schreiben:

Serial.println("\x02" "DF\0x03\r");

Zwischen \0x02 und DF muss dabei der String aufgeteilt werden, da der Compiler sonst versucht \0x02DF als Hex zu parsen und sich beschwert dass der Wert zu groß für einen char ist. Das ist wesentlich lesbarer als da für jedes Zeichen eine Variable zu definieren.

Hi!

Danke dir erstmal für die schnelle Antwort!

Ich habe leider keinen Einfluss auf das was gesendet wird.

Noch kurz: Das was ich jetzt sende ist die Antwort die ich von einem fertigen Gerät erwarte (Blutdruckmessgerät). Ich will nur das Programm von dem Mega schon schreiben und "simuliere" mir mit dem Uno jetzt sozusagen die Antwort des Gerätes.

Aber sehe ich das richtig das

if(c == '\n')

die Abfrage nach dem "Stop" -Zeichen ist? Kann ich das nicht in das CR ändern?

Kornfeld:
Ich habe leider keinen Einfluss auf das was gesendet wird.

In deinem Test-Code hast du aber Einfluss darauf WIE du das schreibst. Das mag gehen, ist aber unnötig kompliziert.

Aber sehe ich das richtig das

if(c == '\n')

die Abfrage nach dem "Stop" -Zeichen ist? Kann ich das nicht in das CR ändern?

Ja, natürlich. CR ist '\r'

Das hat in deinem Code dann nicht gepasst. Du hast CR als Endzeichen beim Senden, aber hast auf LF abgefragt.

Gut das werde ich dann morgen gleich testen! Danke dir auf jedenfall sehr!

Wo hast du das mit dem Befehl Processserial gefunden? Hast du da vielleicht allgemein einen link oder eine Buchempfehlung?
.. also sachen was vielleicht nicht nur die Basics sind.

Das ist eine selbst geschriebene Funktion...

Kann man natürlich auch so machen:

void loop()
{
   if(readSerial())
   {
       Serial1.println(serialBuffer);
   }
}

Aber wenn in loop() noch mehr steht und die Verarbeitung länger wird, ist es besser das auszulagern.

... das ganze mehrmals hintereinander. ca 5-6mal ... oder öfter.

Wie kann ich verhindern das die Ausgabe mehrfach ist?

"5 - 6 mal" Versteh ich nicht ?
Das wird alle 5 Sekunden, unendlich oft, gesendet, weil es in loop steht.
(Na ja, ist noch nicht raus ob es noch unendlich viele 5 Sekunden-Intervalle geben wird, und ob dein Arduino und dein Stromversorger so lange leben werden, aber ... )

Wenn es nur einmal gesendet werden soll, kommt deine Serial.print() - Sequenz ins setup
und du drückst den Reset-Knopf, wenn es gesendet werden soll.

Ein gern genommener Kompromiss zwischen deiner und Serenifly's Schreibweise ist übrigens,
Text der auch als Text lesbar ist, auch so zu schreiben,
und Steuerzeichen so wie du es gemacht hast, zu verwenden.
Also:

const char STX=0x02;
const char ETX=0x03;
const char CR= 0x0D;
const char LF= 0x0A; 

void setup()
{
  Serial.begin (4800);
  delay(500);
  Serial.write (STX);
  Serial.write ("S1;A;C03;M00;P1208010000;R075;T05;;D2;");
  Serial.write (ETX);
  Serial.write (CR);
}

void loop() {} // Danach macht der Uno nix mehr

Also erstens an Serenifly mit dem CR klappt es dann einwandfrei!

Und an Michael.. das Problem war nicht das senden. Das es in der Sendeschleife alle 5s kommt ist nur damit ich es besser nachvollziehen kann was da passiert.. wenn ich mein Gerät letzendlich anschließe wird diese Antwort einmalig kommen.
Und diese hätte ich dann gerne einzeln gehabt und nicht mehrfach.. da war halt im endeffekt einfach der stop falsch gewählt.