Senden von Zahlenwerten über HC-05 und HC-06

Hallo,

ich habe zwei Arduinos. Einer soll Zahlenwerte mit einem HC-05 auf den anderen senden, der mit einem HC-06 ausgestattet ist.
Ich habe beide Sketch soweit gebracht, dass der HC-05 einen Zahlenwert aus einem String in einen float umwandelt und dann ziffer für ziffer rüber schickt.
Der HC-06 empfängt diese dann auch.
Aber wenn ich das dann auf dem Ic2-Display(4x20) ausgeben will, wird immer nur die aktuell gesendete Ziffer angezeigt. Nicht die ganze Zahl.

Meine Frage ist jetzt, wie kann ich die ganze Zahl in einem Schlag schicken?

Hier ist der Sketch vom Slave:

#include <SoftwareSerial.h>
#include <Wire.h>                    // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h>       // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 20, 4);  //Hier wird festgelegt um welches Display es sich handelt

#define ledPin 13
#define rxPin 0
#define txPin 1

SoftwareSerial btSerial(rxPin, txPin);
char btData;
 
void setup()
{
 Serial.begin(9600);  //serieller Monitor wird gestartet, Baudrate auf 9600 festgelegt
 pinMode(13,OUTPUT);  //PIN 13 wird als Ausgang festgelegt
 lcd.init();          //Im Setup wird der LCD gestartet 
lcd.backlight();      //Hintergrundbeleuchtung einschalten 
}
 
void loop()
{
  if(Serial.available()) //wenn Daten empfangen werden...      
  {
    btData = Serial.read();     //..sollen diese ausgelesen werden
    Serial.print(btData);       //Schreiben der Empfangenen Daten
    digitalWrite(ledPin,HIGH);    //Anzeige zur Verbindungsüberprüfung
    lcd.setCursor(0, 0);           //Den Cursor an den Anfang setzen
    lcd.print(btData);              //Das erste Zeichen auf dem Display anzeigen
    delay(1000);                     //1 sec. warten
    lcd.setCursor(1, 0);           //Den Cursor auf das nächste Zeichen setzen
    lcd.print(btData);               //Die nächste Ziffer ins Display schreiben
    delay(1000);                      //warten ... u.s.w
    lcd.setCursor(2, 0);
    lcd.print(btData);
    delay(1000);
    lcd.setCursor(3, 0);
    lcd.print(btData);
    delay(1000);
    lcd.setCursor(4, 0);
    lcd.print(btData);
    delay(5000);
  }
}

Das ist der Sketch vom Master:

String btData = "";      //Definition des Strings für die Messwerte

#include <SoftwareSerial.h>
 
#define ledPin 13
#define rxPin 0
#define txPin 1
 
SoftwareSerial btSerial(rxPin, txPin);

 
void setup()
{
  btSerial.begin(9600);
    while (!Serial)
     {
     ; // Warte auf serielle Kommunikation
     }
  btSerial.println("bluetooth available");
}
 
void loop()
{
  if (btSerial.available())
  {
   btData=12.2;
   Serial.println(btData.toFloat());
   btSerial.println(btData);
   // clear the string for new input:
   btData = "";
   digitalWrite(ledPin, HIGH);
   delay(1000);
  }
}

Gruß
Adruinoboy

Sketch_f_r_Slave.ino (1.31 KB)

Sketch_f_r_Master.ino (626 Bytes)

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Bitte beherzige Tommy56.

Zu Deinem Code am Empfänger:

if(Serial.available()) //wenn Daten empfangen werden...
{
btData = Serial.read(); //..sollen diese ausgelesen werden
Serial.print(btData); //Schreiben der Empfangenen Daten
digitalWrite(ledPin,HIGH); //Anzeige zur Verbindungsüberprüfung
lcd.setCursor(0, 0);
lcd.print(btData);
delay(1000);
lcd.setCursor(1, 0);
lcd.print(btData);
delay(1000);
lcd.setCursor(2, 0);
lcd.print(btData);
delay(1000);
lcd.setCursor(3, 0);
lcd.print(btData);
delay(1000);
lcd.setCursor(4, 0);
lcd.print(btData);
delay(5000);
}

Wenn Du Deinen Code mit dem kommentieren würdest, was Du erwartest, dann wäre Dir geholfen.

Tipp: Du liest ein Zeichen ein, gibst das aus, wartest eine Sekunde, gibst das erneut aus, wartest eine Sekunde, gibst...

Ich bin noch nicht fortgeschritten und bitte um kleinschrittige Anweisen

evtl. möchtest du ja die CmdMessenger Lib einsetzen.

Ich habe einige Kommentare hinzugefügt, ich hoffe dass jetzt klar ist, was ich mit meinem Code erreichen wollte.

Da immer nur eine Ziffer geschickt wird, wollte ich den Cursor um eins verschieben und dann den nächsten Eintrag auf dem Display erscheinen lassen.
Aber das funktioniert nicht. Es erscheint an allen fünf Stellen immer die erste Ziffer, die geschickt wurde.
Im nächsten durchlauf der Loop werden alle 1-sen dann mit 2-en überschrieben uns so weiter.

Ich denke der Trick ist, die ganze Zahl sofort zu schicken. Ich weiß nur nicht wie???

Gruß
Adruinoboy

Der Code passt überhaupt nicht zusammen. Mit read() kannst du keine als String formatierten Gleitkommazahlen einlesen. Sondern nur ein einzelnes Zeichen. Klar zeigt er dir da immer das gleiche Zeichen an.

Ich denke der Trick ist, die ganze Zahl sofort zu schicken

Das Absenden ist zwar unnötig kompliziert, aber der Fehler legt beim Auslesen. Du liest nur ein Zeichen aus. Und es fehlt jegliche Überprüfung ob die Übertragung fertig ist. Du kannst dich nicht darauf verlassen dass der String immer gleich lang ist

Wenn du kein CR + LF am Ende brauchst, macht man übrigens print() statt println()

Welchen Code würdest du vorschlagen?

Laut deinen Links müsste in meinem Fall also folgender Code beim Slave sinnvoller sein!?

btData = Serial.parseInt();

Dann müsste ich also btData als Int deklarieren?

Gruß
Adruinoboy

parseFloat() hast du übersehen?

Es gibt bessere Optionen aber bei deinen Kenntnissen ist es das einfachste

Man könnte auch readString() verwenden. Eigentlich ist hier der Umweg über eine String/Zahl Konvertierung nicht nötig. Schadet aber auch nichts. Und man kann evtl. die Ausgabe so besser formatieren

void loop()
{
if(Serial.available()) //wenn Daten empfangen werden...
{

// Wird ein Zeichen ausgelesen
btData = Serial.read(); //..sollen diese ausgelesen werden

// Wird das eingelesene Zeichen auf dem ser.Mon. ausgegeben
Serial.print(btData); //Schreiben der Empfangenen Daten
digitalWrite(ledPin,HIGH); //Anzeige zur Verbindungsüberprüfung
lcd.setCursor(0, 0); //Den Cursor an den Anfang setzen

// Wird das eingelesene Zeichen auf dem LCD...
lcd.print(btData); //Das erste Zeichen auf dem Display anzeigen
delay(1000); //1 sec. warten
lcd.setCursor(1, 0); //Den Cursor auf das nächste Zeichen setzen

// Dafür müsste erstmal eine neue Ziffer da sein
lcd.print(btData); //Die nächste Ziffer ins Display schreiben

Was fehlt?
Wenn Du einen Ansatz hast, schreibs rein. Keine Angst.
Dir wird geholfen.

Ich habe meinen Code etwas verändert, jetzt liest er die ganze Zahl auf einen Schlag aus. Sehr gut.
Aber hinter der Zahl stehen noch 2 Felder mit horizontalen Linien.
Wahrscheinlich fehlt mir irgendwie eine Endsequenz. Gibt es so etwas, dass er eine Endsequenz direkt mitschickt? Oder kann man das auch einfacher lösen?

Hier der Sketch:

#include <SoftwareSerial.h>
#include <Wire.h>                    // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h>       // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden
LiquidCrystal_I2C lcd(0x27, 20, 4);  //Hier wird festgelegt um welches Display es sich handelt

#define ledPin 13
#define rxPin 0
#define txPin 1

SoftwareSerial btSerial(rxPin, txPin);
float btData;
 
void setup()
{
 Serial.begin(9600);  //serieller Monitor wird gestartet, Baudrate auf 9600 festgelegt
 pinMode(13,OUTPUT);  //PIN 13 wird als Ausgang festgelegt
 lcd.init();          //Im Setup wird der LCD gestartet 
lcd.backlight();      //Hintergrundbeleuchtung einschalten 
}
 
void loop()
{
  if(Serial.available()) //wenn Daten empfangen werden...      
  {
    //Wird ein Zeichen ausgelesen
    btData = Serial.parseFloat();     //..sollen diese ausgelesen werden
    
    //Wird das eingelesene Zeichen auf dem seriellen Monitor ausgegeben
    Serial.println(btData);            //Schreiben der Empfangenen Daten
    digitalWrite(ledPin,HIGH);      //Anzeige zur Verbindungsüberprüfung
    lcd.setCursor(0, 0);            //Den Cursor an den Anfang setzen

    //Wird das eingelesene Zeichen auf dem LCD...
    lcd.println(btData);            //Das erste Zeichen auf dem Display anzeigen
    delay(5000);                     //5sec. warten
  }
}

adruinoboy:
Ich habe meinen Code etwas verändert, jetzt liest er die ganze Zahl auf einen Schlag aus. Sehr gut.

Na geht doch :wink:

Aber hinter der Zahl stehen noch 2 Felder mit horizontalen Linien.
Wahrscheinlich fehlt mir irgendwie eine Endsequenz. Gibt es so etwas, dass er eine Endsequenz direkt mitschickt? Oder kann man das auch einfacher lösen?

Dir fehlt keine Endsequenz. Die hast Du schon und die wird Dir - weil es eigentlich nicht sichtbare Zeichen sind - so angezeigt
Grund ist:

 btSerial.println(btData);

Schau in der Referenz nach, was .println macht und was .read macht.

Das Gegenteil ist offensichtlich der Fall wenn da zu viel am Ende steht

Also .println schickt quasi eine Endsequenz mit "/n".
Was .read macht, daraus wurde ich nicht schlau.
Wie kann ich aber meine zwei Kästchen auf dem Display weg bekommen, damit ich die reinen Zahlenwerte erhalte?

Gruß
Adruinoboy

Vergleiche das und das

Herzlichen Danke, ich meine es verstanden zu haben.
Also println schickt immer den Code mit einem \r und \n hintendran. Mein Empfänger wusste nicht genau, was es damit anfangen sollte und hat daraus horizontale Linien gemacht.
Danke für die Hilfe.

Ich habe also aus dem Sketch erstmal alle println() rausgenommen, es funktioniert besser.

Was mir allerdings aufgefallen ist: Wenn ich den seriellen Monitor nicht öffne, wird die Lampe nicht angeschaltet und das Programm sieht die Bedingung if(serial.available()) als nicht wahr angenommen.
Ich kann mir nicht erklären warum.
Sobald ich den seriellen Monitor öffne, wird die Lampe aktiviert und das Programm läuft wie gewünscht.
Ich freue mich, wenn weiterhin genauso geduldige und kompetente Ratschläge und Hilfestellungen kommen würden, wie bisher.

Wenn ich den seriellen Monitor nicht öffne, wird die Lampe nicht angeschaltet und das Programm sieht die Bedingung if(Serial.available()) als nicht wahr angenommen.
Ich kann mir nicht erklären warum.

Ich schon. Hab mal die Doku angeschaut. Serial.available() liefert die Anzahl angekommener, aber noch nicht per read() gelesener Zeichen. Sei froh, dass kein Müll ankommt, wenn da gar kein Sender angeschlossen ist, und in deinem Fall eine 0 (false) geliefert wird.

adruinoboy:
Mein Empfänger wusste nicht genau, was es damit anfangen sollte und hat daraus horizontale Linien gemacht.

Nein. Der weiß das genau. Steuerzeichen sind nun mal auf Displays nicht druckbar. Das Display verwendet den Speicher an der Stelle einfach für andere Zeichen.

michael_x:
Sei froh, dass kein Müll ankommt, wenn da gar kein Sender angeschlossen ist, und in deinem Fall eine 0 (false) geliefert wird.

Warum ist kein Sender angeschlossen? Das verstehe ich nicht. Ich habe einen Sender und Empfänger. Die finden sich auch.

Oder meinst du, dass ich einen Willkommenstext senden und empfangen muss, damit die Verbindung automatisch startet?
Ich freue mich, wenn du mir praktisch zeigst, was du meinst.

Hi

Das soll heißen, daß die Lib (oder Empfänger) genügend Intelligenz mitbringt, daß ein Sender sicher erkannt wird und - viel wichtiger, kein Sender ebenso erkannt wird.
Anders, wenn die Lib (oder Empfänger) einfach nur rauswirft, was wohl am Empfänger eingetrudelt ist, bekommst Du 'irgend was' - Das können korrekte Daten sein - aber eben auch nicht.
Das zu unterscheiden, ist nicht trivial - macht hier aber wohl Lib (oder Empfänger) bereits für Dich.

Somit ist Das, was Du als Antwort bekommst und nicht Null ist, eine echte Antwort - mit Der man arbeiten kann.

MfG

Hallo,

danke für die Erklärung nochmal. Also ich bekomme zwar sinnvolle Zahlenwerte, aber kannst du mir einen Ansatz zeigen, wie ich die Ausgabe bzw. das Empfangen auch intelligent steuern kann.
Ich würde mich freuen.

Übringens: Sender und Empfänger verbinden sich zwar, aber die Kommunikation startet nicht.

Ich bin euch echt dankbar, wenn ihr mir hierbei helft. Ich habe keinen Ansatz.
Hat keiner einen anregenden Gedanken?