Serenifly:
Daran ist nichts erstaunlich. Schau im Datenblatt gegen Ende unter "DC characteristics". 3,3V wird noch als High erkannt
Das Start/Stop-Bit macht nicht was du denkst. Das ist eine Ebene tiefer um zu erkennen wo ein Byte anfängt. Mit deinem Übertragungsprotokoll hat das rein gar nichts zu tun
Das ist mir schon absolut klar. Diese Start-/Stop-Bits ist eher für ein UART gedacht gewesen. Leider "Streamt" das BMS nur einfach die Daten vor sich hin so rauß, ohne eine Anforderung über eine Zusatzleitung oder ohne das im Herstellerpotokoll so etwas wie eine Sart- oder End-Kennung vorgesehen ist.
Was die Pegel angeht, so wundert es mich umso mehr das es jetzt erst, mit einem Optokopler, funktioniert.
Serenifly:
Bei 9600 Baud dauert ein Zeichen ca. 1ms ( 1 / 9600 * 10 Sekunden). Du kannst das daher nicht in einem Rutsch einlesen! Das wurde dir schon mehrmals gesagt. Man braucht hier keine while-Schleife. Du hast schon eine Schleife mit loop() selbst. Verabschiede dich von dem Gedanken das alles in einem Durchlauf von loop() machen zu müssen
Dein Empfangs-Array lokal in loop() zu deklarieren wo es bei jedem Durchlauf der Funktion neu angelegt wird ist da auch falsch. Das sollte global sein
Wie würde denn in etwa so ein Programm aussehen? Vermutlich würde das dann nur in C gehen oder gibt es da noch Möglichkeiten mit der Arduino IDE?
Serenifly:
Generell ist es ein Problem sich bei sowas mit dem Sender zu synchronisieren. Du kannst natürlich zählen und eine bestimmte Anzahl von Bytes einlesen. Aber dass die genau ein Telegramm darstellen ist unwahrscheinlich. Eher steigst du da irgendwo mittendrin ein.
Man könnte was mit der Zeit machen wenn du sagst dass das nur alle halbe Sekunde geschieht. Also erst mal überprüfen dass z.B. 200ms nichts empfangen wurde. Und dann weiß man dass das man ab dem nächsten Byte einlesen muss. Die Daten die vorher angekommen sind musst man natürlich verwerfen! Das wurde auch schon abgesprochen
Zählen oder etwas mit den Zeiten halte ich für schwierig, aber ich werde in einem Beitrag weiter unten mal Screenshots vom Osziloskop anhängen.
Ich habe mir die letzte .ino jetzt nicht angesehen anmerk
Meine Gedanken gehen in die Richtung, daß Du Daten verpasst.
Die Serial-Funktion hat (meines Wissen) einen Puffer von 64 Byte, die Anzahl der gerade jetzt im Puffer belegten (und damit auslesbaren) Bytes bekommst Du mit Serial.available().
Einzelne Bytes liest Du mit Serial.read() aus, was jedes Mal wieder ein Byte Platz schaffen dürfte.
Wenn der Puffer aber voll ist, gehen entweder Daten verloren, oder werden überschrieben.
In beiden Fällen stimmt dann die Prüfsumme nicht (dafür ist Diese ja auch da).
Hatte hier einen ähnlichen Fall - nur anders herum
Ich habe meinen Puffer (ein Array) mit den Daten gefüllt, bis zu einer Stop-Bedingung.
Danach hing das Programm ... eigentlich auch klar, da ich, sobald 'available' true zurück gibt, in die Auslese-Routiene gesprungen bin, dort aber, da der Puffer voll war, kein Serial.read() auslöste - somit wurde der Puffer auch nicht leerer und mein Programm sah immer noch Daten, Die bearbeitet werden sollen.
Ich habe diese Daten dann einfach weggeschmissen (byte nonsens=Serial.read(); ) - später sollte der Puffer größer sein, als die zu erwarteten Bytes - leider brachte mir mein Code trotzdem immer noch nicht die Daten, Die ich sehen will (laut INet).
MfG
Meine momentane Vermutung ist, das währen der Verarbeitung der Puffer überläuft und es dann zu den Problemen kommt. Momentan wäre mein Lösungsansatzs tatsäclich entweder die Abfrage globaler ausserhalb der loop() zu machen oder den irgendwie dafür zu orgen den Buffer rechtzeitig zu leeren, bin jetzt noch recht ratlos.
belba:
Wie würde denn in etwa so ein Programm aussehen? Vermutlich würde das dann nur in C gehen oder gibt es da noch Möglichkeiten mit der Arduino IDE?
??
Arduino wird in C/C++ programmiert. Die Arduino Software ist keine eigene Sprache sondern nur eine API
Zählen oder etwas mit den Zeiten halte ich für schwierig
Das ist nur der Fall weil du Schwierigkeiten mit der Programmierung hast. Das ist relativ einfach
Momentan wäre mein Lösungsansatzs tatsäclich entweder die Abfrage globaler ausserhalb der loop() zu machen oder den irgendwie dafür zu orgen den Buffer rechtzeitig zu leeren, bin jetzt noch recht ratlos.
Das ist keine Lösung. Du musst das Einlesen mit dem Anfang des Telegramms synchronisieren. Und du musst beachten dass die serielle Schnittstelle im Vergleich zum Prozessor sehr langsam ist
Arduino wird in C/C++ programmiert. Die Arduino Software ist keine eigene Sprache sondern nur eine API
Das ist nur der Fall weil du Schwierigkeiten mit der Programmierung hast. Das ist relativ einfach
Das ist keine Lösung. Du musst das Einlesen mit dem Anfang des Telegramms synchronisieren. Und du musst beachten dass die serielle Schnittstelle im Vergleich zum Prozessor sehr langsam ist
Serenifly:
??
Arduino wird in C/C++ programmiert. Die Arduino Software ist keine eigene Sprache sondern nur eine API
Das ist nur der Fall weil du Schwierigkeiten mit der Programmierung hast. Das ist relativ einfach
Das ist keine Lösung. Du musst das Einlesen mit dem Anfang des Telegramms synchronisieren. Und du musst beachten dass die serielle Schnittstelle im Vergleich zum Prozessor sehr langsam ist
Hast du vielleicht Links die mir weiterhelfen könnten? Bei de Lösungsansatz stehe ich in der Tat auf dem schlauch
SkobyMobil:
Hallo,
gebe doch bitte einmal einen aussagekräftigen Link zu Deinem "BMS".
Auch einen Link zum Datenblatt oder ECHTNAME wäre nicht schlecht.
Das ist doch alles Rätselraten hier...
Gruß und Dank
Andreas
Eigentlich habe ich mir das wirklich einfaher vorgestellt und daher kein Hersteller usw. genannt, es sollte doch eine Arduino standart Aufgabe sein dachte ich mir...
Zwar verfügt das System über eine Bluetooth Schnittstelle, aber wenn man ein Android7 Gerät hat, dann hat man Pech gehabt. In diesem Android gibt es ein Bug der das Pairing verhindert, also ist das kein Weg.
Weiterhin möchte ich auch gerne diese Daten an der Batterie selbst ohne Bluetooth-Gefrickel mal einfach so ablesen können und wenn ich diese Daten dann noch mitloggen oder an andere Geräte weitergeben könnte wäre das super, aber es geht mir in Moment erst mal um ein einfaches Display an der Batterie.
Wichtig zu wissen wäre noch das das BT-Modul nur aufgesteckt ist und das nur über das BT-Modul auch nur gewisse Parameter eingestellt werden können.
Ich habe darauf hin den Hersteller angeschrieben ob die mir nicht das Protokoll am BT-Modul mal zusenden könnten. Als Antwort hatte ich erhalten das die dieses Protokoll nicht freigeben, aber das es ja noch den "Extended Data Input" am OUT-Modul geben würde, dazu bekam ich ein PDF mit der Protokollbeschreibung, so kam ich zu diesen Arduino-Projekt.
Da ich bisher im Netz keine weitere Seite gefunden habe, welche dieses PDF anbietet, werde ich den Hersteller wieder anschreiben und um Erlaubnis um die Weitergabe anfragen. Zudem habe ich gerade bei der Durchsicht noch gesehen das das IN-Modul ein "Extended Data Output" Anschluss hat. Ich werde auch darüber mal nachfragen.
Zu dem Protokoll möchte ich noch die Screenshots vom Oszilloskop mal hier Posten:
Hallo,
im Datenblatt steht "nichts" geschrieben. Wie Du schon sagtest, die legen
ihr Protokoll nicht offen, aber-
Das Ding kann BT.
Bastel Dir doch einen BT<->Arduino<->Seriell Adapter. Das mit der seriellen
Schnittstelle würde ich erst einmal begraben.
Einfach mal ein BT-Shield mit vernünftiger Lib an den Arduino und versuchen
eine Verbindung aufzubauen. Das wäre schon die halbe Miete.
Gruß und Spaß
Andreas
Hallo,
nein, jetzt hat er nichts. Er stochert mit einem ZeitMessGerät im Nebel rum
und denkt sich das er Bit´s und Byte´s erkennen kann.
BT ist ein Standart. Das Protokoll lieg offen.
Er drückt also am BMS eine Taste, die BT-Übertragung beginnt, der Arduino
empfängt es und gibt es über den seriellen Monitor aus.
Da dieses Vorgehen ein Standart ist, kann er es mit hilfe des BT-Protokoll
entschlüssel.
Und so kann man sich Stück für Stück vorarbeiten.
Gruß und Spaß
Andreas
SkobyMobil:
Hallo,
im Datenblatt steht "nichts" geschrieben. Wie Du schon sagtest, die legen
ihr Protokoll nicht offen, aber-
Das Ding kann BT.
Bastel Dir doch einen BT<->Arduino<->Seriell Adapter. Das mit der seriellen
Schnittstelle würde ich erst einmal begraben.
Einfach mal ein BT-Shield mit vernünftiger Lib an den Arduino und versuchen
eine Verbindung aufzubauen. Das wäre schon die halbe Miete.
Gruß und Spaß
Andreas
Das Protkoll an dem besagten "Extended Data Output" ist, zumindest für mich, offen. Ob ich das PDF weiterveröffentlichen darf weiß ich noch nicht, aber durch die *.ino Datei die ich oben gepostet habe, ist es eigentlich ja schon offen.
Was die BT-Lösung angeht so ist das BT-Modul aufsteckbar. Ich habe auch schon den den Anschlüssen etwas herum gesnifft. Es ist eine Bidirektionale Verbindung. Nach einem senden von "$" werden Daten geliefert. Möglicherweise ist es das Protokoll welches in dieser PDF beschrieben wurde:
Das mit dem BT-Modul werde ich auf jeden Fall mal im Auge fassen und mir genauer ansehen.
Noch etwas zu Frage ob via Draht oder BT.
Auf der untersten Ebene steht da nur die art der Verbindung. Ob nun Draht mit seinen Start-/Stop-Bits oder mit BT seinen Protokollspezifikationen. Beides sind für mich die unteren Protokollebenen welche ich nutzen kann und die son mal durch Standarts festgelegt wurden.
Die aus meiner Sicht wichtigen Unterschiede bestehen in den höheren Protokollebenen (=wann werden welche Daten in welcher Form übertragen) welch ja vom Hersteller des BMS vorgegeben werden. Und hier hab ich die Wahl zwischen BT mit unbekannten höheren Protokoll vom Hersteller (allerdings habe ich da eine Vermutung wie das aufgebaut sein könnte, siehe mein Post oben) oder eben den Draht wo ich eine Protokollbeschreibung habe und die ich grundsätzlich auch verstehe.
Ein weiterer Unterschied wäre noch das ich via BT die Settings umstellen kann, was aber quasi nur ein einziges mal beim Bau der Batterie benötigt wird, beim Draht habe ich diese Möglichkeit nicht.
Hallo,
"Und wie kommen die Daten dann aus dem Bluetooth Modul?"
Mußt Du immer nein sagen, wenn ich ja sage? hä!?
Du nimmst einen echten Arduino, dazu ein BT-Modul mit einer Lib, von denen Du weißt, das sie 100%tig
mit dem Arduino arbeiten.
Wenn Du jetzt ein anderes BT-Gerät nimmst, dann kann der Arduino dessen Daten empfangen und
sichtbar machen.
Da BT ein Standart ist kannst Du diese Daten entschlüsseln.
Es wird doch immer das selbe gesendet...
BT-Kommando-Zeug´s -> Nutzer-Daten -> BT-Kommando-Zeug´s
Die Nutzer-Daten stehen immer an gleicher Stelle, also findest Du die auch.
Gruß und Spaß
Andreas
Folgendes habe ich mal für ein (möglicherweise) ähnliches Projekt verwendet, um herauszufinden, wie ein Telegramm aufgebaut ist. Genauere Beschreibung im Sketch.
Vielleicht kann dir das beim ersten Auswerten helfen.
/* Seriell sollen "Telegramme" empfangen werden.
* Es sind aber keine speziellen Anfangs- oder Endzeichen
* vorhanden. Allerdings gibt es "längere" Pausen ZWISCHEN
* den einzelnen "Telegrammen". Nur durch Auswertung dieser
* Pause kann der Beginn eines neuen "Telegramms" ermittelt
* werden.
* Dieser Sketch dient zum Reverse Engineering.
* Zeichen, die am seriellen Monitor nicht darstellbar sind
* werden in HEX dargestellt, also Zeichen kleiner ASCII 32
* und größer ASCII 126.
*/
#include <AltSoftSerial.h>
AltSoftSerial altSerial; // Arduino UNO: RX Pin 8, TX Pin 9
unsigned long lastMillis;
const unsigned long pause = 200; // anpassen je nach Notwendigkeit
const int msgBuffSize = 70; // max. Zeichen im "Telegramm"
int msgBuffer[msgBuffSize];
int msgBufferIndex = 0;
void checkForNewData() {
if (altSerial.available()) {
if (millis() - lastMillis > pause) {
msgPrint();
}
msgBufferIndex++;
if (msgBufferIndex > (msgBuffSize - 1)) {
msgBufferIndex = 0;
}
msgBuffer[msgBufferIndex] = altSerial.read();
lastMillis = millis();
}
}
void msgPrint() {
Serial.print(msgBufferIndex + 1);
Serial.print(" Zeichen empfangen:\t");
for (int i=0; i<=msgBufferIndex; i++) {
int inByte = msgBuffer[i];
if ((inByte < 32) || (inByte > 126)) { // nicht Datstellbares als HEX ausgeben
Serial.print(" 0x");
Serial.print(inByte, HEX);
}
else {
Serial.write(inByte);
}
}
Serial.println();
msgBufferIndex = -1;
}
void setup() {
Serial.begin(9600);
altSerial.begin(9600);
Serial.println("Ich lausche mit AltSoftSerial");
Serial.print("Pause (ms): ");
Serial.println(pause);
}
void loop() {
checkForNewData();
}
SkobyMobil:
Du nimmst einen echten Arduino, dazu ein BT-Modul mit einer Lib, von denen Du weißt, das sie 100%tig
mit dem Arduino arbeiten.
Wenn Du jetzt ein anderes BT-Gerät nimmst, dann kann der Arduino dessen Daten empfangen und
sichtbar machen.
Da BT ein Standart ist kannst Du diese Daten entschlüsseln.
Es wird doch immer das selbe gesendet...
BT-Kommando-Zeug´s -> Nutzer-Daten -> BT-Kommando-Zeug´s
Die Nutzer-Daten stehen immer an gleicher Stelle, also findest Du die auch.
Für die Aufgabe des Framings (also wann Datagramme anfangen und wann sie aufhören) und deren Decodierung ist es völlig egal ob die seriellen Daten über Bluetooth kommen, oder über Drähte.
Du musst es mir ja auch nicht glauben, vielleicht hat dein Bluetooth Modul ja auch SPI oder I2C.
Alle einzelnen Bluetooth Module die ich bisher hatte, hatten eine serielle Schnittstelle.
Whandall:
Du musst es mir ja auch nicht glauben, vielleicht hat dein Bluetooth Modul ja auch SPI oder I2C.
Alle einzelnen Bluetooth Module die ich bisher hatte, hatten eine serielle Schnittstelle.
Ich gebe dir da völlig recht, aber bei dem BT-Modul handel es sich um dieses:
bei diesem Modul werden neben der Stromversorgung, auch die UART-Anschlüsse (Pin 13 und 14) benutzt, sowie zwei weitere PIO-Anschlüsse. Das bekräftigt meine Vermutung das es sich um "einfache" Serielle kommunikation handelt und nicht um USB, I2C oder SPI (die haben separate Anschlusspins)
ich habe das selbe BMS gekauft und wäre ebenfalls an einer Lösung interessiert. Bist Du schon weiter gekommen? Falls ja, wäre ich sehr an den Ergebnissen interessiert. Falls nein - finden wir eventuell gemeinsam eine Lösung. Könntest Du mir die Schnittstellenbeschreibung per PN zukommen lassen?