Go Down

Topic: Bluetooth Serial, zweistellige Variable (Read 237 times) previous topic - next topic

markusweih


wno158

#1
Sep 13, 2020, 07:58 pm Last Edit: Sep 13, 2020, 08:02 pm by wno158
Ich auch.

EDIT: Na gut, verrätst Du uns auch, woran du so sehr verzweifelst? Dann lässt sich besser helfen :)

TriB

Von welchem Typ wäre denn die 2stellige Variable?

So lange die Eingaben sammeln, bis ein Zeilenumbruch kommt, dann zusammenfügen.

my_xy_projekt

Von welchem Typ wäre denn die 2stellige Variable?
So lange die Eingaben sammeln, bis ein Zeilenumbruch kommt, dann zusammenfügen.
Ich versteh Deine Aufgabenstellung vielleicht falsch, was gut geht und flexibel ist:
char sammeln.
https://de.wikibooks.org/wiki/C%2B%2B-Programmierung/_Weitere_Grundelemente/_Zeichenketten

TriB

Die Zeichen sammeln ist so oder so nötig. Char macht mutmaßlich am meisten Sinn!

Die Frage, die sich mir stellt ist wie es dann weiter geht. Handelt es sich um eine zweistellige Ganzzahl 0-99 oder um Binär, Hexadezimal, etc..
Gibt es Trenn- oder Zeilenendzeichen?

Ohne den Infos und/oder dem Wissen woran es akut beim TE scheitert, können wir eh nur raten.

markusweih

Danke für die konstruktiven Antworten. Dürfte ich meinen Sketch bitte hier einkopieren, er ist auch kurz.
Knackpunkt ist meines Erachtens die Zeile "value = SerialBT.read();"


/*
App: Über App Inventor programmiert, verbindet sich per Bluetooth mit ESP32 und übergibt Variable
OLED: 128x64 WxH Monochrome, korrekt verbunden mit ESP 32, SSD1306 Treiber am I2C Port.
*/

#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
#include <SPI.h>
#include <Wire.h>
#include "SSD1306Ascii.h" 
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3C
SSD1306AsciiWire oled;
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16

int value = 0; //Deklaration Variable

void setup() {
  Serial.begin(9600); 
  SerialBT.begin("Ich bin ein ESP32 mit Bluetooth"); //Bluetooth device name
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Addresse des OLED Displays
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
 
  display.display(); // Show initial display buffer content on screen or Adafruit splash screen
  delay(2000); // Pause
  Wire.begin();
  Wire.setClock(400000L);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
}

void loop() {
  if (Serial.available()) {
    SerialBT.write(Serial.read());
  }
  if (SerialBT.available()) {
    value = SerialBT.read();
    Serial.write(value);
    oled.setFont(fixed_bold10x15); // Auswahl der Schriftart auf dem OLED
    oled.clear(); //Löschen der aktuellen Displayanzeige
    oled.print(value-48); // Umrechnung serieller Wert in Ausgabewert
  delay(20);
  }}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

my_xy_projekt

Danke für die konstruktiven Antworten. Dürfte ich meinen Sketch bitte hier einkopieren, er ist auch kurz.
Was sind denn Antworten die nicht konstruktiv sind? - ok. ich stelle die Frage hinten an.

Der darf gerne auch lang sein, aber grundsätzlich sollten die Codetags Also das </>-Symbol verwendet werden, um möglichst allen Lesern auf den unterschiedlichsten Geräten Zugang zu verschaffen - und das ebenso lesbar zu machen.

Quote
Knackpunkt ist meines Erachtens die Zeile "value = SerialBT.read();"
Der Knackpunkt dürfte eher sein, das Du versuchst irgendwas aus irgendwelchen Quellen zusammen zu kopieren und das Konstrukt dann nicht die erwartete Lösung bringt.
Das kann am Verständnis liegen, oder am Unwillen, oder sonst was.
Erklär es.

Quote
Code: [Select]

/*
App: Über App Inventor programmiert, verbindet sich per Bluetooth mit ESP32 und übergibt Variable
OLED: 128x64 WxH Monochrome, korrekt verbunden mit ESP 32, SSD1306 Treiber am I2C Port.
*/

#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
#include <SPI.h>
#include <Wire.h>
#include "SSD1306Ascii.h"  
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3C
SSD1306AsciiWire oled;
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16

int value = 0; //Deklaration Variable

void setup() {
 Serial.begin(9600);  
 SerialBT.begin("Ich bin ein ESP32 mit Bluetooth"); //Bluetooth device name
 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Addresse des OLED Displays
   Serial.println(F("SSD1306 allocation failed"));
   for(;;);
 }

 display.display(); // Show initial display buffer content on screen or Adafruit splash screen
 delay(2000); // Pause
 Wire.begin();
 Wire.setClock(400000L);
 oled.begin(&Adafruit128x64, I2C_ADDRESS);
}

void loop() {
 if (Serial.available()) {
   SerialBT.write(Serial.read());
 }
 if (SerialBT.available()) {
   value = SerialBT.read();
   Serial.write(value);
   oled.setFont(fixed_bold10x15); // Auswahl der Schriftart auf dem OLED
   oled.clear(); //Löschen der aktuellen Displayanzeige
   oled.print(value-48); // Umrechnung serieller Wert in Ausgabewert
 delay(20);
 }}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2


HotSystems

Nachdem du deinen Sketch lesbar in Code-Tags gesetzt hast, darfst du auch gern beschreiben, was der Sketch machen soll und was dieser dann nicht macht. Oder was er für Fehler zeigt.

Dann fällt uns evtl. eine Fehlersuche leichter.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

TriB

Du liest ein Zeichen aus.
Allerdings möchtest Du zwei Zeichen auslesen.

Dementsprechend benötigst Du z.B. ein charArray[] in welches Du die Eingaben (temporär) überträgst.
Im nächsten Schritt baut man daraus dann wieder eine Ganzzahl zusammen.

Da kann man eine schöne while(SerialBT.available())-Schleife verwenden, die so lange Dein Puffer-Array füllt, bis:
  • Der Puffer voll ist
  • Die Daten komplett sind


Dann hast Du die gepufferten chars, welche die Zahl des Zeichens repräsentieren, umrechnen.
Ein Trick ist es, einfach das Zeichen für die `0`abzuziehen, damit man auf den echten Wert kommt.

Also, kommt eine 25 rein, pufferst Du die Werte 50 (Dezimalwert für die 2) & 53 (Dezimalwert für die 5).
50 - 48 (Dezimalwert für die 0) = 2
53 - 48 = 5

Zusammenbauen, fertig!

agmue

#9
Sep 17, 2020, 10:52 am Last Edit: Sep 17, 2020, 03:42 pm by agmue
Ein Programm zum Testen, da ich die App nicht habe, mit dem seriellen Monitor:

Code: [Select]
// getestet mit ESP32
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("\nStart");
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Addresse des OLED Displays
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print("Zwei Zahlen eingeben!");
  display.display(); // Show initial display buffer content on screen or Adafruit splash screen
  delay(1000);
}

void loop() {
  if (Serial.available()) {
    char zeichen[3];
    zeichen[0] = Serial.read();
    zeichen[1] = Serial.read();
    zeichen[2] = '\0';
    Serial.println(zeichen);
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print("Zeichen: ");
    display.print(zeichen[0]);
    display.print(zeichen[1]);
    display.display();
  }
}


EDIT: Entsprechend #10 geändert, denn '\0' muß man Platz einräumen! Danke!

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Tommy56

Der Code ist fehleranfällig.
1. Es ist nicht sicher, dass zeichen  mit '\0' abgeschlossen ist (lokale Variable), also besser
Code: [Select]

    char zeichen[3];  // <---- + Platz für '\0'
    zeichen[0] = Serial.read();
    zeichen[1] = Serial.read();
    zeichen[2] = '\0';
    Serial.println(zeichen);


2. Es ist nicht sicher, dass beide Zeichen im Realfall schon da sind (beim Seriellen Monitor als Quelle geht das)

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Serenifly

Dass man nicht zweimal direkt hintereinander read() machen kann solltest du eigentlich wissen. Die serielle Übertragung ist auch bei hohen Baudraten immer langsamer als der Controller. Genau deswegen verwendet man ja normalerweise Endzeichen

Sauber:
Code: [Select]

const unsigned int READ_BUFFER_SIZE = 3;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  char* str = readLine(Serial);  //liefert einen Zeiger ungleich 0 wenn das LF eingelesen wurde
  if (str != nullptr)
  {
    Serial.print("Eingelesen: "); Serial.println(str);

    byte nr = atoi(str);
    Serial.print("Konvertiert: "); Serial.println(nr);
}

char* readLine(Stream& stream)
{
  static byte index;
  static char buffer[READ_BUFFER_SIZE];

  while (stream.available())
  {
    char c = stream.read();

    if (c == '\n')              //wenn LF eingelesen
    {
      buffer[index] = '\0';     //String terminieren
      index = 0;
      return buffer;            //melden dass String fertig eingelesen wurde
    }
    else if (c >= 32 && index < READ_BUFFER_SIZE - 1)   //solange noch Platz im Puffer ist
    {
      buffer[index++] = c;    //Zeichen abspeichern und Index inkrementieren
    }
  }
  return nullptr;               //noch nicht fertig
}

Und am Ende ein Linefeed als Abschluss schicken. Sonst geht es nicht



Als Alternative kann man die Ziffern direkt aufsummieren wenn sie reinkommen. Das ist bei so einfachen Sachen ganz praktisch. Aber auch da muss man irgendwie das Ende erkennen

Go Up