Frage zur Übermittlung mit Bluetooth und zu geringem Strom

Kann es sein, dass der USB-Port nicht genügend Strom liefert, um den Arduino Uno und ein Bluetooth-Modul zu betreiben?
Ok zugegeben ich habe aufgrund von Strommangel den USB-Port meines Fernsehers verwendet, da ich nicht gleichzeitig den Arduino mit USB am Notebook versorgen kann und die Bluetooth-Kommunikation über das Notebook erledigen darf.
Dabei ist mir gestern aufgefallen, dass ich nur nach jedem 3-4 Signal eine Antwort erhielt. Ansonsten kam im Serial Monitor nur eine "-1" als Antwort.
Jetzt habe ich ein altes FritzBox-Netzteil mit 12V und 1,2A gefunden und plötzlich bekomme ich bei einem im Serial Monitor getipptem "A" auch ein "A" als Antwort.

Was mich aber noch interessiert, warum kann ich z.B. "ABC" im Serial Monitor tippen und bekomme aber 3 Antworten mit jeweils den Buchstaben "A", "B" und "C" anstatt nur eine Antwort "ABC" zurück?

Ich habe den Standard-Code "SoftwareSerial" aus den Examples verwendet und nur den Output angepasst, um zu sehen wer mir antwortet.
Achso, und warum bekomme ich nie das "Hello, world?" zu sehen?
Entschuldigt bitte diese vielen Fragen. :blush:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(0, 1); // RX, TX

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
}

void loop() // run over and over
{
  if (mySerial.available())
  {
    Serial.print("mySerial: ");    
    Serial.write(mySerial.read());
    Serial.println("");
  }
  if (Serial.available())
  {
    Serial.print("Serial: ");
    mySerial.write(Serial.read());
    Serial.println("");
  }
}

Kann es sein, dass der USB-Port nicht genügend Strom liefert, um den Arduino Uno und ein Bluetooth-Modul zu betreiben?

Könnte schon sein, aber auch nicht.
Du mußt uns schon das Model des BT-Moduls verraten und den Schaltplan Deines Projekts.

Du kannst nicht die Pins 0 und 1 für die Software emulierte Schnittstelle nehmen; da ist bereits eine Serielel schnittstelele die für die Komunikation mit dem PC verwendet wird.

mySerial.read() bzw Serial.read() holt immer nur 1 Byte vom Buffer und da Du es sofort verschickst und Du danach mit Serial.println(""); ein NewLine schickst hast Du:
A
B
C
anstatt
ABC auf dem Terminal.

Grüße Uwe

Hallo Uwe,

danke für deine Erklärung.
Ich nutze das HC-06 Bluetooth Modul mit der Standardverkabelung am Uno.
Ansonsten ist nichts weiteres angeschlossen.
Nach dem Upload entferne ich immer das USB-Kabel, dann wird der Arduino vom Netzstecker weiter mit Strom versorgt.
Über mein Smartphone (S3) verwende ich "BlueTerm" als App, um mit dem Bluetoth Modul zu kommunizieren.

Da, wie du schon sagtest, der Arduino sofort auf jede Eingabe antwortet, wodurch ich immer nur ein Zeichen abschicken kann, was muss dann ändern?
Kann ich im Code soetwas schreiben wie "warte bis das Zeichen '#' erscheint und schreibe dann alle bisher angefallen Zeichen".
Nur weiß ich nicht wie ich die bisherigen Werte zwischenspeichern soll?
Oder reicht dafür eine einfache Variable?
Hm ... ich werde das mal eben testen.

Edit:
Schade! Das war wohl zu einfach gedacht.
Ich habe mir eine Variable angelegt:

char *memory = "";

Und dann diese versucht zu befüllen:

    if (mySerial.read() == '#')
    {
      Serial.print("Speicher: ");
      Serial.write(memory);
      Serial.println("");
      memory = "";
    } else {
      memory += mySerial.read();
    }

Doch leider kommt da nichts raus. Wenn ich aber "memory" einen festen Wert gebe, dann gibt er diesen aus.
Aber scheinbar kann ich keine Buchstaben in einer Variablen speichern bzw. anhängen. :blush:

Ich glaube, dein Problem mit den einzeln gesendeten Zeichen ist gar keines... Kommentiere mal diese Codezeile aus:

Serial.println("");

Damit sendest du doch erst den Zeilenumbruch.

Leider war es das nicht.
Ich habe eher das Gefühl, dass ich mit "char" keine Strings speichern kann.
Also muss ich das wohl irgendwie anders angehen.
Ich habe schon den Datentyp "String" ausprobiert.
Allerdings macht Arduino nicht mit, wenn ich

Serial.write(String(variable));

versuche auszuführen. Es gibt wohl noch keine write Funktion dafür:

no matching function for call to 'HardwareSerial::write(String&)

Oder ich verstehe da etwas nicht. Tippe da mal aufs Zweite. :blush:

Strings in C sind NULL-terminierte Arrays aus char.

z.B. so als Konstante.
char str[] = "test";

Du kannst dann ein leeres Array anlegen:

const int bufferSize = 31;
char buffer[bufferSize];
memset(buffer, 0, bufferSize);

Das hat Platz für 30 Zeichen (das 31. ist der Terminator). Die Variable "buffer" ist dann automatisch ein char*

char *memory = "" geht aus einem einfach Grund nicht:
Es ist einfach nur ein Pointer. Speicher wurde dabei nirgends reserviert. Dafür brauchst du die Array Klammern [] und musst die Größe angeben.

Beachte auch, dass die += Syntax mit Arrays nicht funktioniert. Sowas geht bei String Objekte nur weil die den Operator überladen haben.

Du kannst aber einfach einen Index mitzählen und in das Array schreiben:

int index = 0;
buffer[index++] = Serial.read();

Du musst dann entweder memset() jedesmal machen bevor du anfängst den String einzulesen (und nicht nur einmal bei der Deklaration), oder wenn du fertig bist das machen:
buffer[index] = '\0';
Das ist ganz, ganz wichtig. Wenn der Terminator fehlt, wissen anderen Funktionen nicht wo der String aufhört.

Und aufpassen, dass du nicht über den Puffer hinaus schreibst. Also sowas in der Art machen:

while(Serial.available() && index < bufferSize - 1)
{
     buffer[index++] = Serial.read();
}

-1 da der letzte Index 30 ist und noch Platz für den Terminator sein muss

Wenn du dann Serial.read() erst mal in einem char abspeicherst bevor du in das Array schreibst, kannst du den zuletzt eingelesenen Character auch abfragen und das Auslesen abbrechen. Was sich da auch stark anbietet ist entweder ein Line Feed (10) oder Carriage Return (13). Das kann man im Serial Monitor einstellen, dass es automatisch angehängt wird.

z.B.:

while(Serial.available() && index < bufferSize - 1)
{
     char c = Serial.read();

     if(c == 13)     //Carriage Return
     {
          buffer[index] = '\0';
          break;     //while-Schleife abbrechen
     }
     else
          buffer[index++] = c;
}

Bei dieser Vorgehensweise auch beachten, dass die Übertragung eines Zeichens bei 9600 Baud ca. 1ms dauert. Wenn das erste Zeichen da ist und if(Serial.available()) anschlägt, ist der Rest also noch unterwegs. Da kann man dann nach dem if und vor der while-Schleife ein kurzes Delay einbauen um auf das Ende der Übertragung zu warten. Das Delay stört bei zeitkritischen Anwendung, aber für dich reicht das erst mal.

if(Serial.available())
{
    delay(35);
    const int bufferSize = 31;
    char buffer[bufferSize];
    //hier auch memset() wenn man diese Variante wählt

    int index = 0;
    while(Serial.available() && index < bufferSize - 1)
    {
    }

    //eingelesenen String hier verarbeiten
}