Hallo,
ich bin noch recht neu in der Programmierung, ich möchte aber versuchen Daten die ich über eine serielle Schnittstelle empfange auszulesen und einen bestimmten Wert an den seriellen Monitor (oder später auf eine SD-Karte) auszugeben.
Bei den Daten die ich empfange handelt es sich um 163 Bytes die immer mit "0x56 0xAB 0x56 0x02" beginnen. Ich benötige aber nur die Werte an Stelle 118, 119 und 120. Diese würde ich gerne am seriellen Monitor ausgeben.
Mit folgendem Code werden alle Werte ausgeben, natürlich ohne Ende.
Gibt es eine einfache Möglichkeit nur die gewünschten Werte auszugeben und dann fünf Minuten zu warten um die Werte erneut auszugeben?
wenn du genau beschreiben würdest was du da auslesen willst (link, Datasheet,...) dann hat vieleicht jemand was fertiges, und wenn nicht was fertiges dann zumindest Lust an etwas dauerhaften mit dir daran zu arbeiten.
vor allem wie die Nachricht aufgebaut ist wird benötigt, insbesondere auch ob es ein Endzeichen gibt
zum Lernen wie man ein Gerät über Seriell liest, rate ich dir das Serial Input Basics Tutorial durchzumachen und genau so zu verfahren wie dort beschrieben: Serial Input Basics - updated
Wenn du weist wie man die Daten in ein char array einliest, kannst du dann auch gezielt auf einzelne Indeces zugreifen.
Der Vorgang ist ja grundsätzlich übersichtlich:
-- Einlesen bis zu einem Endkriterium (Endflag, Zeichenanzahl, Stream- Ende... was auch immer)
-- Auswerten
-- nur alle 5 Minuten einen Wert ausgeben
Danke für den Link, ich hatte schon mehrere Posts dazu gelesen, aber anscheinend immer die falschen bzw. waren die nicht hilfreich für mich. Werde es damit einmal versuchen.
Mein Ansatz basiert auf Serial Input Basic, gepackt in eine Klasse für das Gerät.
/*
Serial Eheim
Serial Receive Example for a fix length telegram with 4 start flags
Valid telegram
56 AB 56 02 01 02 03 ...
56 AB 56 02 start flag / start marker
01 02 03 ... 112 + 47 bytes
based on a discussion in: https://forum.arduino.cc/t/daten-aus-einer-serieller-schnittstelle-auslesen-auswerten/1073809/4
by noiasca
2023-01-06
*/
class Device {
protected:
static const uint8_t numChars = 163; // receiver buffer size
uint8_t receivedChars[numChars]; // an array to store the received data
uint8_t ndx = 0; // length of received message
boolean newData = false; // flag to indicate when new data is complete
Stream &stream; // a reference to the serial interface
void (*cbOnNewData)(); // gets called after we received a full message
// extracted payload data
uint8_t valueA = 0; // 118
uint8_t valueB = 0; // 119
uint8_t valueC = 0; // 120
void delBuffer() {
memcpy(receivedChars, "", sizeof(receivedChars));
ndx = 0;
}
void parseData() // parse data and if according to specification store to internal variable
{
valueA = receivedChars[118];
valueB = receivedChars[119];
valueC = receivedChars[120];
}
void parseLine() // process a telegram
{
//Serial.print(F("I56: This just in ... ")); Serial.println(receivedChars); // output all
parseData();
if (cbOnNewData) cbOnNewData();
}
public:
Device(Stream &stream)
: stream(stream) {
delBuffer();
}
uint8_t getValueA() // return the last valid result
{
return valueA;
}
uint8_t getValueB() // return the last valid result
{
return valueB;
}
uint8_t getValueC() // return the last valid result
{
return valueC;
}
void setOnNewData(void (*cbOnNewData)()) // set a callback function. Gets called when new data was received
{
(*this).cbOnNewData = cbOnNewData;
}
void update() // run this member function in loop()
{
// 4 start flags, fix length
int rc = stream.read();
if (rc >= 0)
{
// check first 4 positions:
if (ndx == 0 && rc != 0x56 ||
ndx == 1 && rc != 0xAB ||
ndx == 2 && rc != 0x56 ||
ndx == 3 && rc != 0x02 )
delBuffer();
else // accept value
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = 0;
parseLine();
}
}
}
}
};
// create the sensor object and hand over the Serial interface to use:
HardwareSerial &mySerial = Serial; // use Hardware Serial (for example for testing with the PC)
//#include <SoftwareSerial.h> // on an Uno you can use SoftSerial
//SoftwareSerial mySerial(2, 3); // RX, TX
// On a Mega you can simply use a reference to an existing HW Serial:
//HardwareSerial &mySerial = Serial1;
Device device(mySerial); //create an instance of the device and handover a Serial (Stream) Interface
void output() // simple output of data
{
Serial.println(device.getValueA());
Serial.println(device.getValueB());
Serial.println(device.getValueC());
Serial.println();
}
void timerOutput() // a timer to output data to serial
{
static uint32_t previousMillis = 0; // time management
const uint16_t interval = 3000; // interval to display data
if (millis() - previousMillis >= interval) {
previousMillis = millis();
output();
}
}
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
//device.setOnNewData(output); // register a callback function which gets called when a new telegram was received
}
void loop() {
device.update(); // you must call the .update() method in your loop()
timerOutput();
}
Leider habe ich jetzt ein ganz anderes Problem. Und dies führt wahrscheinlich dazu das ich nicht die Werte empfange.
Ich habe mir die Daten auch nochmal alle an den seriellen Monitor weiterleiten lassen und dort empfange ich immer anstatt AB nur FFFFFFAB. Das gleiche passiert auch wenn ich nur AB mit Hterm sende.
AB und noch einige andere werden immer mit FFFFFF am Anfang empfangen.
Weiß hier jemand zufällig woran das liegen könnte?
Ich lese aus deinem Post keine nachvollziehbare Information heraus mit der man dir helfen könnte.
Baudrate richtig? Verkabelung korrekt? Module richtig angeschlossen? Außerdem hast du noch nicht verlinkt, um welches Gerät es sich hierbei handelt.
Also sorry @noiasca, was soll das?
In seinem letzten Post steht, das die Ausgabe nicht ASCII sondern UTF ist
Das Gerät interressiert keinen, ausser Dich. Wozu?
120 Bytes seriell lesen ist doch nu keine Raketenwissenschaft.
Du versuchst jetzt aber nicht jedem aufzuzwingen zu benennen, mit was er die auf dem Arduino zu empfangenen Bytes sendet?
PS: Das Ding kommt aus dem Industriebereich und ist kundenspezifisch konfiguriert. Was denkst Du wieviele User es gibt, die genau diesen Geber einsetzen?
Es reicht ein einziger der danach sucht und der dann vieleicht froh ist, etwas zu finden. Vieleicht. Vieleicht auch nicht. Die Information um welches Gerät es sich handelt zu teilen kann also Vorteile bringen. Diese Information zu verheimlichen ... da sehe ich keinen Vorteil.
Es reicht auch ein einziger Eintrag um den Code für andere Anwendungen unattraktiv zu machen, so das diese den ausschliessen.
Siehe die Thematic der ganzen Solardinger udn eHZ, die alle SML sprechen, aber jeder meint ausgerechnet seiner nicht.
Worauf willst Du jetzt eigentlich hinaus? Dass es keinen Sinn macht, eine Anfrage hier im Forum so anzulegen, dass möglichst viele Informationen zum Themenkomplex preis gegeben werden?
Also so, dass mögl. viele von dem Thread profitieren könnten? Weil sich ja evtl. eh alles wieder ändert?
Das ich dieses Nachtreten um den Sendertypen nicht verstehe.
Es werden 120 bytes gelesen.
Es ist bekannt wie die Nachricht aufgebaut ist.
Es ist klar,was gebraucht wird.
Mir erschliesst sich nicht, warum da nun unbedingt drin stehen muss "Ich benutze Gerät 0815 vom Hersteller 4711"
Welchen Mehrwert hat die Information über den Sender? Ausser das diese Information dahin führt, das andere Nutzer die nur 112bytes von irgendeinem anderen Gerät lesen wollen dann von vornherein schon weiterscrollen, weil ist ja speziell für was anderes...