serielle Kommunikation funktioniert nicht (Bluetooth HC-06)

Hallo,

ich versuche mich an der Kommunikation zwischen Serial 0 und Serial 1. Diesmal mit der standardmäßigen Endeerkennung Linefeed. An Serial 1 hängt der Bluetooth Adapter HC-06, welches mit meinem Smartphone verbunden ist.

Auf dem Rechner hab ich mit dem Arduino IDE serial Monitor und meinem Lieblingstool HTerm probiert. Auf dem Smartphone ebenso mit 2 Apps.

Das Problem ist, vom Rechner aus kann ich alles senden was ich möchte, es kommt überall an. Vom Smartphone aus kann ich machen was ich will, es passiert absolut nix.

Überall ist auf Linefeed eingestellt. Carrier return hab ich auch probiert und die beide zusammen auch. Alles egal.

Was mich auch wundert ist, dass ich den Buffer auf 17 eingestellt habe. Abzüglich der 0 Termination bleiben eigentlich nur 16 Zeichen für die Übertragung. Ich kann aber 20 Zeichen zum Bsp. vom Rechner aus senden. Kommt alles an. ???

// Arduino Mega 2560

const int SERIAL_BUFFER_SIZE = 17;
char _serialBuffer0[SERIAL_BUFFER_SIZE];
char _serialBuffer1[SERIAL_BUFFER_SIZE];  


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


void loop() {
  
read_serial_0();

read_serial_1();

}  // loop Ende

// ------------------------------------------------------------------------------------

void read_serial_0()  {  
  
   static unsigned int index0;
   if (Serial.available() > 0)  {     
      char c = Serial.read();
      if (c >= 32 )  {
         _serialBuffer0[index0++] = c;
      }
      else if(c == '\n')  {     // Endeerkennung 'LineFeed'
         _serialBuffer0[index0++] = '\0';
         index0 = 0;
         Serial.println (_serialBuffer0);
         Serial1.println(_serialBuffer0);
      }
   }
}


void read_serial_1()  {  
  
   static unsigned int index1;
   if (Serial1.available() > 0)  {        
      char c = Serial1.read();
      if (c >= 32 )  {
         _serialBuffer1[index1++] = c;
      }
      else if(c == '\n')  {      // Endeerkennung 'LineFeed'
         _serialBuffer1[index1++] = '\0';
         index1 = 0;
         Serial.println (_serialBuffer1);
         Serial1.println(_serialBuffer1);
      }
   }
}

Was mich auch wundert ist, dass ich den Buffer auf 17 eingestellt habe. Abzüglich der 0 Termination bleiben eigentlich nur 16 Zeichen für die Übertragung. Ich kann aber 20 Zeichen zum Bsp. vom Rechner aus senden. Kommt alles an. ???

Natürlich! Weil du nirgends abfragst ob der Index noch gültig ist! Das ist in C/C++ tödlich. Bei Puffer0 geht das, weil er dann die restlichen Daten einfach in Puffer1 schreibt.

if(c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
{
}

Wenn es vom PC aus funktioniert und beim Smartphone nicht, wird das Problem wohl am Handy liegen.

Hallo,

upps, peinlich, leuchtet ein. Danke.

und was macht der Befehl nochmal?
_serialBuffer1[index1++] = '\0';

den habe ich auch schon so probiert, ohne Imkrementierung.
_serialBuffer1[index1] = '\0';

Ändert aber nichts am Problem. Was ist richtig? Der Befehl hängt doch nur die  Null Termination als letztes Zeichen ran. Oder?
Mit Inkrementierung wäre die vorletzte Stelle leer und dann kommt die Null Terminierung. Richtig? Also wäre ohne Imkrementierung richtiger?
else if(c == '\n')  {      // Endeerkennung 'LineFeed'
         _serialBuffer1[index1++] = '\0';

Ist an der Stelle egal. Am Ende nicht zu inkrementierten ist semantisch wohl korrekter, macht aber funktional keinen Unterschied.
Der Null-Terminator kommt am Ende. Ob du das jetzt inkrementierst oder nicht ist wurschst, da der Index in der nächsten Zeile auf 0 gesetzt wird.

Mit Inkrementierung wäre die vorletzte Stelle leer und dann kommt die Null Terminierung. Richtig?

Nein. Das ist ein Postfix Inkrement!

http://de.wikibooks.org/wiki/C++-Programmierung/_Einführung_in_C++/Rechnen%28lassen%29#Inkrement_und_Dekrement

Hallo,

scheinbar werden vom Smartphone oder vom HC-06 keinerlei Endezeichen gesendet. Warum auch immer. Keine Ahnung.

Hab den Code wieder umgebaut auf meine Krücke mit @ als Startzeichen und # als Endeerkennung. Funktioniert. Aber das ist doch ehrlich gesagt nicht normal. Oder? Ist der Code erstmal so gesehen sauber?

Im Forum sind doch mehrere Leute unterwegs mit dem Bluetooth Adapter. Wie macht Ihr das?

const int SERIAL_BUFFER_SIZE = 17;
char _serialBuffer0[SERIAL_BUFFER_SIZE];
char _serialBuffer1[SERIAL_BUFFER_SIZE];  


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


void loop() {
  
read_serial_0();

read_serial_1();

}  // loop Ende

// ------------------------------------------------------------------------------------

void read_serial_1()  {  
  
   static unsigned int index1;

      if (Serial1.available() > 0)  {		
          char c = Serial1.read();
          if(c == '@')  {
            _serialBuffer1[index1] = '\0';
            index1 = 0;
          }
          
          
          else if(c == '#')  {      // Endeerkennung '#'
             _serialBuffer1[index1] = '\0';
             index1 = 0;
             Serial.println (_serialBuffer1);
             Serial1.println(_serialBuffer1);
          }
          
          
          else if (c >= 32 && index1 < SERIAL_BUFFER_SIZE - 1)  { 
            _serialBuffer1[index1++] = c;
            //index1 = 0;
            //Serial.println (_serialBuffer1);
            //Serial1.println(_serialBuffer1);
          }
      }
}


void read_serial_0()  {  
  
   static unsigned int index0;
   if (Serial.available() > 0)  {		
      char c = Serial.read();
      if (c >= 32 && index0 < SERIAL_BUFFER_SIZE - 1 )  {
         _serialBuffer0[index0++] = c;
      }
      else if(c == '\n')  {     // Endeerkennung 'LineFeed'
         _serialBuffer0[index0] = '\0';
         index0 = 0;
         Serial.println (_serialBuffer0);
         Serial1.println(_serialBuffer0);
      }
   }
}

Die Nullterminierung muss nach dem Endzeichen kommen. Nicht gleich am Anfang. Startzeichen brauchst du dann eigentlich nicht.

Hallo,

genau, ist sinnlos. Was mich noch wundert ist, im Terminal auf dem Rechner bekomme ich nach der Ausgabe wie gewünscht noch \F\n in Miniatur, kaum lesbar hinten angehangen. Heißt das es wird doch eine standardmäßige Kennung geschickt? Oder macht das HTerm selbst?

Jetzt sollte der Code passen? In meiner alten Version mit nur Starterkennung mußt der neue Befehl 2x gesendet werden. Es wurde immer vorher noch einmal der alte gesendet/empfangen. Deswegen bin ich an die Sache nochmal ran. Mit der Endeerkennung sollte das besser klappen.

Nur sollte man nicht noch eine saubere Starterkennung einbauen? Sonst wird ja alles eingesammelt was irgendwie über die “Leitung” reinkommt. Bis irgendwann einmal das Endezeichen kommt.

@ all: Im Forum sind doch mehrere Leute unterwegs mit dem Bluetooth Adapter. Wie macht Ihr das?

void read_serial_1()  {  
  
   static unsigned int index1;

      if (Serial1.available() > 0)  {		
          char c = Serial1.read();
          
          if(c == '@')  {      // Endeerkennung '@'
             _serialBuffer1[index1] = '\0';
             index1 = 0;
             Serial.println (_serialBuffer1);
             Serial1.println(_serialBuffer1);
          }
          
          
          else if (c >= 32 && index1 < SERIAL_BUFFER_SIZE - 1)  { 
            _serialBuffer1[index1++] = c;
          }
      }
}

Doc_Arduino: Nur sollte man nicht noch eine saubere Starterkennung einbauen? Sonst wird ja alles eingesammelt was irgendwie über die "Leitung" reinkommt. Bis irgendwann einmal das Endezeichen kommt.

Das kommt auf dein Protokoll an und was du da genau machst. Wenn da auch aus irgendeinem Grund Müll gesendet wird, kann man es natürlich machen (dann reicht es da einfach den Index auf 0 zu setzen. Sonst nichts). Wenn immer nur sinnvolle Informationen ankommen braucht man es nicht.

Hallo,

eigentlich wird kein Müll bewußt gesendet. Dachte nur an Störungen, die vielleicht auftreten könnten. Ich überleg mir das noch. Danke soweit.

Hallo,

hab das mal probiert. Ich bekomme jedoch das Startzeichen @ mit eingelesen. Das soll aber außen vor bleiben. Wie lösche ich das? Was ich auch nochmal fragen muß ist, was ist der Unterschied zwischen " und ’ Zeichen?

if(c == “S”)
oder
if(c == ‘S’)

const int SERIAL_BUFFER_SIZE = 17;
char _serialBuffer0[SERIAL_BUFFER_SIZE];
char _serialBuffer1[SERIAL_BUFFER_SIZE];  

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

void loop() {
  
read_serial_0();

read_serial_1();

}  // loop Ende

// ------------------------------------------------------------------------------------

void read_serial_1()  {  
  
   static unsigned int index1;
   static boolean start_read = false;
   
      if (Serial1.available() > 0)  {		
          char c = Serial1.read();
          
          if(c == '@')  {                    // Starterkennung '@'
             _serialBuffer1[index1] = '\0';
             index1 = 0;
             start_read = true;
          }
          
          if(start_read == true)  {
             if(c == '#')  {                   // Endeerkennung '#'
                _serialBuffer1[index1] = '\0';
                index1 = 0;
                start_read = false;
                Serial.println (_serialBuffer1);
                Serial1.println(_serialBuffer1);
             }
             else if (c >= 32 && index1 < SERIAL_BUFFER_SIZE - 1)  {  // alles lesen was kein Steuerzeichen ist
               _serialBuffer1[index1++] = c;
             }
          }   
      }
}


void read_serial_0()  {  
  
   static unsigned int index0;
   if (Serial.available() > 0)  {		
      char c = Serial.read();
      if (c >= 32 && index0 < SERIAL_BUFFER_SIZE - 1 )  {
         _serialBuffer0[index0++] = c;
      }
      else if(c == '\n')  {     // Endeerkennung 'LineFeed'
         _serialBuffer0[index0] = '\0';
         index0 = 0;
         Serial.println (_serialBuffer0);
         Serial1.println(_serialBuffer0);
      }
   }
}

' ' für einzelne Zeichen " " für eine Zeichenkette

In deinem Fall if(c=='S')

Es wäre gut möglich, dass das '@' nicht vom Programm richtig interpretiert wird. Versuch es mal mit if(c=='0x40')

Hallo,

mit 0x40 passiert nichts. Demnach sollte das @ schon passen. Alles was davor steht wird ignoriert.
Wenn ich mir meinen Code so anschaue, wird

a) auf das @ gewartet
b) wenn @ erkannt wird, wird index1 genullt
c) und dann wird mit der letzten else if genau das aktuelle Zeichen schon eingelesen, was ja noch das @ ist. Irgendwie blöd.

Die Erweiterung mit, wenn c nicht @ ist, funktionert nicht. Ein komplett leerer Buffer wird übertragen. Schreibweise falsch?

else if (c >= 32 && c== !'@' && index1 < SERIAL_BUFFER_SIZE - 1)

Edit:
klar, falscher Syntax. :smiley:
So paßt das. :slight_smile:

else if (c >= 32 && c!='@' && index1 < SERIAL_BUFFER_SIZE - 1)

Mit dem @ Zeichen teste ich gleich nochmal.

Ob deine Abfrage so funktioniert, glaube ich eher nicht aufgrund der 2. Abfrage.

else if (c >= 32 && !(c== '@') && index1 < SERIAL_BUFFER_SIZE - 1)

Hallo,

zeitliche Überscheidung. :)

Nutzt Du dein HC05 oder HC06 mit einem Smartphone und nutzt die standardmäßigen LF, CR Kennungen? Wenn ja, welche Terminal App nutzt Du?

Hallo,

ich habe die HC05 Module auch bereits mit dem Handy betrieben. Habe damals viele Programme genutzt bin dann letzten endes bei Blue Term stehen geblieben. LF und CR wird mitgesendet.

Meine Abfrage funktioniert vom Grundgedanken ähnlich.

#define UART0_BUFFER_MAX_LEN 16
static volatile char uart0_buffer[UART0_BUFFER_MAX_LEN + 1] = "";
static volatile uint8_t uart0_buffer_complete = 0;		// String komplett empfangen
static volatile uint8_t uart0_buffer_count;

ISR(USART0_RX_vect)
{
	unsigned char nextChar;
	
	// Daten aus Puffer lesen
	nextChar = UDR0;
	
	if( uart0_buffer_complete == 0 )
	{
		if( nextChar != '\n' &&	nextChar != '\r' &&	uart0_buffer_count < UART0_BUFFER_MAX_LEN )
		{
			uart0_buffer[uart0_buffer_count] = nextChar;
			uart0_buffer_count++;
		}
		else
		{
			uart0_buffer[uart0_buffer_count] = '\0';
			uart0_buffer_count = 0;
			uart0_buffer_complete = 1;
		}
	}
}

Hallo,

sieht eigentlich im großen und ganzen ähnlich aus. Da es tausende Apps gibt. BlueTerm von pymasde.es oder BlueTerm+ von Michael Jentsch? Woran erkennst Du sicher das LF, CR mitgesendet wird?

Hab mal eben geschaut. Ich habe die Version von pymasde.es drauf. Sollte aber bei der anderen genauso gehen. In den Einstellungen kann ich angeben, ob ich CR und/oder LF mitsenden möchte.

Bei meiner Funktion ist es egal, ob nun CR oder NL kommt. Beide werden gleich behandelt. Wenn der String gefüllt ist, muss er erst mit uart0_buffer_complete abgerufen und zurückgesetzt werden.

Hallo,

naja, einstellen kann ich viel. Ob das wirklich so ist, wäre die Frage, sonst würde mein ursprünglicher Code funktionieren. Und Du sendest wirklich vom Smartphone über BT an die Arduino Serial 0 ?

Zu BlueTerm. Wie gibt man etwas ein? Muß man blind auf die Tastatur tippen und Enter? Mir fehlt da irgendwie ein Eingabefenster. Empfangen geht.

Hallo,

hab nochmal rumprobiert. Ich kann machen was ich will. Die Standardzeichen werden entweder nicht gesendet oder nicht erkannt. Keine Ahnung. Mit irgendwelchen selbstdefinierten Erkennungszeichen funktioniert das. Seltsam. BlueTerm kann ich nicht bedienen. Bekomme nicht mal ein lokales Echos angezeigt. Obwohl das eingestellt ist. Bin wohl zu blöd dazu. :disappointed_relieved:

Ich lasse das jetzt sein und nutze wieder "Bluetooth Terminal" von nextprototypes .... ,da kann ich Button mit Befehlen definieren.

Danke an alle Helfer!

Gerade nochmal getestet, also Local Echo geht bei mir, jedoch wundert es mich, dass er alle Texteingaben automatisch versendet. Hatte im Hinterkopf, dass dies nur beim bestätigen mit Enter geschieht.

Schau dir ansonsten uconnectHex an. Leider keine Echo Ausgabe, aber dort kannst gut testen, ob er CR/LF annimmt. Ich teste lieber mit Putty am PC. Dort weiß ich, was ich einzustellen hab und man kann mit der richtig CR einstellung auf Texte überschreiben.

Doc_Arduino: Und Du sendest wirklich vom Smartphone über BT an die Arduino Serial 0 ?

Kein Arduino. Sind die Attiny841 die ich derzeit im Einsatz hab. Programmiert über ISP und an TX0/RX0 hängt das BT Modul fürs debugging.