PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Unverständliches Verhalten bei Bluetooth-Verbindung



fredyxx
10.02.2017, 07:43
Hallo,

dieses Arduino-Programm empfängt Text über eine serielle Schnittstelle von einem BT-Modul und schreibt diesen in den Seriellen Monitor:



int led = 13;
void setup()
{
Serial.begin(250000);
Serial2.begin(9600);

pinMode(led, OUTPUT);
digitalWrite(led, LOW);
}
void loop()

{
if (Serial2.available())
{
Serial.print("value = ");
String value = Serial2.readStringUntil('\n');

Serial.println(value);
if (value == "*10|9|2#")
{
digitalWrite(led, HIGH);
}
else if (value == "*10|11|3#")
{
digitalWrite(led, LOW);
}

}
}



Wenn ich diese Signale von einer App "Ardroid" aus dem PlayStore sende, erscheint "value = *10|9|2#" sofort auf dem SM.
Wenn ich diesen Text von einer mit dem AppInventor selber erstellten App sende, erscheint zuerst mit merkbarer Verzögerung "value = " und mit weiterer leichter Verzögerung dann "*10|9|2#".
Ich kann mir das nicht erklären, wie es möglich ist, dass das Arduino-Programm den gleichen Text empfängt, aber anders reagiert.

Den Befehlsblock im AppInventor zeigt das Bild. Was die App "Ardroid" macht weiß ich nicht.

32408

vG
fredyxx

i_make_it
10.02.2017, 08:15
Ich kann mir das nicht erklären, wie es möglich ist, dass das Arduino-Programm den gleichen Text empfängt, aber anders reagiert.

Wie hast Du denn das Timing der beiden sendenden Applikationen verglichen, damit Du Dir sicher bist, das sich das Verhalten des Empfängers ändert?

Wie sieht es denn aus wenn die App aus dem Playstore ein compiliertes Programm ist und der AppInventor z.B. selbst in Java geschieben ist und die Befehlsblöcke als YAIL Code von einem Interpreter verarbeitet werden?
Dann wäre das Timingverhalten der App ganz anders wie das einer gut compilierten.
Was das unterschiedliche Timing am Ziel eher erklärt als ein quellselektives Timingverhalten des abgebildenten Arduino Codes.

Genau sagen könnte man das aber nur wenn man BT Sniffing betreibt und so das Zeiliche Verhalten beider Sendungen vergleichen kann.
Oder zumindest mit einem Spectrumanalyzer das zeitliche Verhalten der gesendeten Funkwellen vergleicht.

fredyxx
10.02.2017, 12:25
Wie hast Du denn das Timing der beiden sendenden Applikationen verglichen, damit Du Dir sicher bist, das sich das Verhalten des Empfängers ändert?


Das ist visuell am SM ganz deutlich zu erkennen.


Wie sieht es denn aus wenn die App aus dem Playstore ein compiliertes Programm ist und der AppInventor z.B. selbst in Java geschieben ist und die Befehlsblöcke als YAIL Code von einem Interpreter verarbeitet werden?

Zu diesen Details kann ich nichts sagen.

Das unterschiedliche Timingverhalten durch die Apps könnte ich ja verstehen, aber der Arduino hat einen Empfangspuffer der seriellen Schnittstelle, da steht 2 x das gleiche drin und trotzdem ist das Verhalten des Programms deutlich unterschiedlich. Das leuchtet mir eben nicht ein.

vG
Fredyxx

i_make_it
10.02.2017, 19:49
Ich würde schon auf der Senderseite schauen.


value = *10|9|2#
1234567812345678


Beim einen mal bekommst Du 16 Byte Nutzdaten am Stück beim anderen je 8 Byte und dann wieder 8 Byte.

Versuch doch mal 18-22 Zeichen zu senden und schau mal was da vom Timing her passiert.
Das müsste ja, wenn es Byteweise aufgeteilt wird, bei AppInventor noch langsamer gehen und dann auch auf drei mal kommen.

HaWe
10.02.2017, 19:55
woher weisst du, dass es am Empfänger / dem Arduino liegt?
Es könnte doch auch an unterschiedlich schnellen Sendern liegen?

Nur ein mögliches Erklärungsmodell, es kann ntl auch andere Ursachen haben:

Sobald nur 1 einziges angekommenes Zeichen das "available" anzeigt, gibt der Arduino bereits aus:

if (Serial2.available()) {
Serial.print("value = ");

da muss der Rest der Zeichen noch gar nicht da sein.
Denn jetzt fängt er erst an, den Rest des Strings einzulesen:

String value = Serial2.readStringUntil('\n');
Serial.println(value);

Wenn die ganzen Zeichen nun lange brauchen, bis sie Sender-seitig hinterhergedackelt kommen, dauert es halt mal mehr, mal weniger lange, bis alle vorhanden sind und vollständig angezeigt werden können. Dabei werden sie nicht byte-weise geschrieben, so wie sie eintrudeln, sondern erst, wenn sie vollständig sind, d.h. wenn der string bis zum '\n' vollständig ist!

fredyxx
10.02.2017, 23:22
Beim einen mal bekommst Du 16 Byte Nutzdaten am Stück beim anderen je 8 Byte und dann wieder 8 Byte.

Verstehe ich leider nicht. "value = " kommt ja nicht vom Tablet, sondern vom MEGA an SM.


Versuch doch mal 18-22 Zeichen zu senden und schau mal was da vom Timing her passiert.

Ändert nichts.


Sobald nur 1 einziges angekommenes Zeichen das "available" anzeigt, gibt der Arduino bereits aus:

if (Serial2.available()) {
Serial.print("value = ");

da muss der Rest der Zeichen noch gar nicht da sein.
Denn jetzt fängt er erst an, den Rest des Strings einzulesen:

Wäre eine Möglichkeit. Würde aber doch bedeuten, dass der Sendebefehl meiner App den Text byteweise rüberschickt, während Ardroid den Text immer als Block sendet. Es müsste also unterschiedliche Sendebefehle geben.

Ich habe auch mal hinter "if (Serial2.available())" ein delay (1000) eingefügt, was aber nur das "value = " verzögert, die Verzögerung zum *10|9|2# bleibt aber trotzdem. Ich dachte, damit den eintrudelnden Bytes die Zeit zu geben, die sie bis zum letzten Zeichen brauchen. Oder ruht bei delay auch das Einlesen der Zeichen von der SS?

Noch mal zur Erinnerung: mit Ardroid kommt "value = *10|9|2#" immer sofort und gleichzeitig!

Ich habe mal 2 Videos angefügt. Die sind zwar verwackelt und verschwommen, lassen aber den Unterschied trotzdem erkennen.


https://youtu.be/1qGACxkRK_w


https://youtu.be/taQKpf47ovk

Danke für eure Ideen.

vG
fredyxx

inka
11.02.2017, 08:08
du musst die videos bei youtube öffentlich machen...

fredyxx
11.02.2017, 18:38
Habe ich gemacht!

inka
11.02.2017, 18:55
hab mir die videos angesehen, das unterschiedliche verhalten würde ich den unterschiedlichen "sender" apps zuschreiben. Übrigens, soviel ich weiss, blockiert ein delay wirklich alles...

fredyxx
12.02.2017, 09:57
hab mir die videos angesehen, das unterschiedliche verhalten würde ich den unterschiedlichen "sender" apps zuschreiben. Übrigens, soviel ich weiss, blockiert ein delay wirklich alles...

Aber du kannst mir wohl auch nicht sagen, wie man einen Sendebefehl, anders als oben gezeigt, ausführen kann, damit er wie bei der App "Ardroid" wirkt.

vG

fredyxx

inka
12.02.2017, 10:54
leider nein, ich kenne den app-inventor nicht, aber das verhalten wird schon ein anderes sein als bei Ardroid...

Peter(TOO)
12.02.2017, 10:57
Hallo fredyxx,

Aber du kannst mir wohl auch nicht sagen, wie man einen Sendebefehl, anders als oben gezeigt, ausführen kann, damit er wie bei der App "Ardroid" wirkt.
Das ist jetzt halt der Unterschied zwischen der Klötzchen-Programmierung und einer Programmiersprache!

Logisch machen beide Varianten das Selbe, die Wege sind aber unterschiedlich.

Über eine Programmiersprache kann man alles steuern und hat auch die Übersicht, was unmittelbar zusammengehört. Man kann also in deinem Fall die Teil-Texte zuerst in einem Puffer zusammensetzen und dann den gesamten Puffer ausgeben. Man weiss, dass zwischen dem ersten und dem zweiten Teil nicht etwa 10 Sekunden noch etwas anderes gemacht werden muss.

Bei der Klötzchen-Programmierung braucht man definierte Zustände, wenn so ein Klötzchen abgearbeitet ist. Dazu gehört halt auch, dass Sendepuffer sofort geschrieben werden. So ein einzelnes Klötzchen weiss nicht, wie es nach ihm weiter geht.
Ein weiterer Punkt ist noch, dass die Klötzchen-Geschichte langsam ist. Da ist für jedes Klötzchen zuerst einiges vorzubereiten und nach Beendigung wieder aufzuräumen. Zudem ist das meistens ein Interpreter.

In beiden Varianten muss zwischen den beiden Teil-String noch etwas gerechnet werden. Bei den Klötzchen fällt die Rechenzeit halt auf. Vermutlich ist bei beiden Varianten bei der Ausgabe eine Pause dazwischen, aber 1/10 Sekunde fällt nicht wirklich auf.

MfG Peter(TOO)

fredyxx
27.02.2017, 17:47
Hallo,

endlich habe ich die Ursache gefunden, die nichts mit AppInventor oder Klötzchen-Programmierung zu tun hat, und wenn man die Lösung kennt, primitiv ist!

In meiner ersten Frage seht ihr, dass ich beim Einlesen eines empfangenen Telegramms als Endezeichen ein \n erwarte.

Vom Tablet hatte ich gesendet:

32445

Richtig ist aber:

32446

Damit klappt nun alles super schnell und ich bin happy.

Trotzdem danke für eure Hilfeversuche.

vG

fredyxx

HaWe
27.02.2017, 19:09
Immerhin hat es sich bestätigt, dass es ursächlich nicht, wie ursprünglich von dir vermutet, am Empfänger/dem Arduino liegt, sondern Sender-seitig.
Dass es der Sender-Programmiercode war, ist sicher gut, da solche Fehler beseitigt werden können.
(y)

HaWe
04.03.2017, 08:38
noch ein Hinweis zu der Klötzchen-Programmierung :
Diese bauen (fast) ausschließlich auf Interpretern auf, die einen mehr oder weniger vorverarbeiteten Zwischencode (oft Bytecode) erst noch während der Laufzeit in ausführbaren Code übersetzen müssen, bevor er dann ausgeführt werden kann.
Ich habe einmal verschiedene Benchmark-Tests zu diesen IDEs durchgeführt. Dabei hat sich bestätigt, dass viele(!) dieser Interpreter-Systeme (Klötzchen oder auch Text-Basiert) bis zu 100x langsamer sind als native Executables (per gcc oder clang).
Es gibt aber auch sehr viele Interpreter, die schlauer sind, z.B. der JIT-compiler ("Just-In-Time") von Java (C# Mono macht es ähnlich) - vereinfacht ausgedrückt: hier übersetzt der Compiler während des Interpreter-Betriebs häufig benutzte Teile des Codes in Executables, die dann genau so schnell sind wie C-compilierte executables.
Und tatsächlich haben Java-JIT- und C#-basierte Interpreter fast genaus so schnell abgeschnitten wie native Executables, wenn der Code öfter ausgeführt wurde - beim ersten Mal waren sie nur 1/10 so schnell.
Ältere oder einfachere Java-Compiler waren dagegen immer deutlich langsamer (1/20).

Gerade auf Androids laufen viele Apps per Java, auch mit JIT-Compilern.
Und gerade Klötzchen-Programmierung setzt ot auf Java auf, und daher kann es durchaus sein, dass nach ein paar Sekunden dein Klötzchen-Code schon ähnlich schnell ist wie "richtig" compilierter - dennoch muss man den Intepreter kennen bzw. testen, denn er kann möglicherweise auch dauerhaft z.B. nur 1/100 der erreichbaren Geschwindigkeit bringen.