[Solved!] Serial.read(): Empfangenes weiterverarbeiten (RS232)

Hallo,

aktuell benötige ich für ein Projekt eine RS232-Verbindung. Deshalb habe ich mir eine kleine Schaltung mit einem MAX232 aufgebaut, damit ich am Arduino eine RS232-Verbindung habe. Die RS232 benötige ich, damit ich Messwerte von einer Wetterstation abholen kann. (Die Uhr am Arduino soll darüber auch nachgestellt werden.)

Das Senden von Befehlen über die RS232-Schnittstelle funktioniert schon mal problemlos.
Leider hab' ich Probleme mit dem Empfangen von Daten.

Da ich in Sachen RS232-Kommunikation mit dem Arduino so gut wie keine Ahnung habe, brauche ich eure Hilfe, da ich unteranderem ein Verständnisproblem damit habe.

Ich habe folgenden Code aus dem Internet (ein bisschen angepasst habe ich ihn):

#define STRLEN 16
char buffer[STRLEN];
int  bufferIndex = 0;

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

void loop(){
 if (Serial.available()){
    char retTime = Serial.read();
    if (retTime == '\n' || retTime == ':' || retTime == '\r'){
      buffer[ bufferIndex ] = 0;
    } else {
      buffer[ bufferIndex++ ] = retTime;
      Serial.print(retTime);
    }
 }
}

Dieses Codestückchen soll die Uhrzeit über die RS232 abholen. Funktioniert eigentlich auch ganz gut: Gebe ich z.B. 14:20:55 wird mir 142055 zurückgegeben. Diese 6-stellige Zahl kann ich dann einfach zerlegen.

Da das Gerät an der RS232 aber nicht nur rein die Uhrzeit, sondern "Uhrzeit: 14:20:55\n\r" zurückgibt, muss ich mit einem substring arbeiten. Da geht das Problem aber schon los, wie bekomme ich ein char in einen String?

Dasselbe Problem habe ich auch bei den Wetterdaten. Die Daten werden von der Wetterstation als ACII-Klartext übertragen. Die Daten habe ich dann auch wieder in einem char, welches aber zu einem String verwandelt werden muss, damit ich die Daten weiterverarbeiten kann.

Das Umwandeln von String zu Int/ Long ist dann wieder einfach:

long time = DerSring.substring(6,11).toInt();

Ein Verständisproblem habe ich aber dennoch:
Was ist denn das?/ der? char retTime? Das ist doch einfach ein großes Array, indem jedes Zeichen drin ist,
mit einem eigenen Index?

Ich hoffe mal, dass mein Ansatz mit substrings zu arbeiten schonmal richtig ist....

Viele Grüße
webworker

Die Daten habe ich dann auch wieder in einem char, welches aber zu einem String verwandelt werden muss, damit ich die Daten weiterverarbeiten kann.

Nein. Du hast ein ein Array aus char. In C sind Strings nichts anders als Null-terminierte char Arrays:

Damit kann man problemlos weiter arbeiten.

Vergiss das mit subString() gleich wieder. Das ist für die Arduino String Objekte. Du hast hier aber C Strings. Diese sind für Anfänger kryptischer, aber weit flexibler und mächtiger. Die Arduino String Klasse wäre brauchbar wenn sie mehr Funktionen abdecken würde. Aber sie ist sehr rudimentär und dazu noch ineffizient.

Für C Strings gibt es in der AVR libc zig Funktionen, viele davon aus der Standard C string.h Lib:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html

Damit kannst du letztlich viel mehr machen als mit der Arduino String Klasse.

Eine leichtgewichtige Möglichkeit zur Wandlung gibt es z.B atoi(). Array to Integer:
http://www.cplusplus.com/reference/cstdlib/atoi/

char buffer[] = "Uhrzeit:    14:20:55";
byte hour = atoi(buffer + 12);
byte minute = atoi(buffer + 15);
byte second = atoi(buffer + 18);

Hier bist du mit den Indices festgelegt, aber wenn die immer gleich sind - was hier wohl der Fall ist - passt es. Man könnte aber auch problemlos den Index der ersten Zahl berechnen. Wenn das nur ein Leerzeichen ist, musst du die Indices auf 9/12/15 anpassen

Etwas aufgeblähter, aber sehr schön ist sscanf():
http://www.cplusplus.com/reference/cstdio/sscanf
http://www.cplusplus.com/reference/cstdio/scanf/

int hour, minute, second;
sscanf(buffer, "%*[^0-9]%d:%d:%d", &hour, &minute, &second);

Das hier geht anscheinend nicht mit byte, da byte lediglich unsigned char ist und der Compiler da wohl mit den Datentypen durcheinander kommt. Deshalb hier int statt byte.

Statt %*[^0-9] (alles was nicht 0-9 ist) sollte theoretisch auch %*s: gehen, aber da matcht er nur den String, aber wandelt danach nicht die Zahlen...

Das ist kürzer, aber braucht auch deutlich mehr Flash Speicher. Wobei man es auch noch optimieren kann, so dass der Format String nicht im RAM steht:

#include <avr/pgmspace.h>

sscanf_P(buffer, PSTR("%*[^0-9]%d:%d:%d"), &hour, &minute, &second);

Übrigens ist dein Array mit 16 Zeichen zu klein für den String!! Selbst "Uhrzeit: 14:20:55" bräuchte 18 Zeichen. Eins mehr als die sichtbaren Zeichen für das '\0' am Ende. Du brauchst noch mehr wenn da wirklich so viele Leerzeichen drin sind und das kein Formattierungsfehler war.

Außerdem sollte das "retTime == ':'" raus. Damit bricht er schon nach dem ersten Doppelpunkt ab. Du willst den kompletten String einlesen und danach parsen.

Und noch ein Fehler:
Du musst bufferIndex wieder auf 0 setzen, wenn du einen String eingelesen hast. Bei dir geht das einmal. Danach hast du einen Speicherüberlauf. Das ist katastrophal. Hier merkst du es vielleicht noch nicht, abgesehen davon das es nicht mehr geht, aber in einem größeren Programm würde er dir da den Speicher von anderen Variablen einfach überschreiben.

Hallo Serenifly,

vielen vielen Dank für deine Antwort. Ich werde mir heute Abend mal die aufgezeigten Webseiten ausführlich anschauen und auch einiges ausprobieren. Aktuelle funktioniert das Stellen der Uhr über den Serial Monitor.

Jetzt stehe ich aber vor dem nächsten Hindernis... Das, was von der Wetterstation kommt sieht so aus:

\r\nData :  2.03.14 14:50\r\n
(... kleine Pause ...)
14.8333  0.5 ???   7.6 ???.?   0.0 ----.- ----.- ---.- ---.- ----.- 02.03.14 14:50\r\n
END OF DATA\r\n

Mich interessiert aber nur der Mittlere Teil mit den Daten, wie komme ich an den ran? Mit "\r und \n" als Stopzeichen kommt bei mir nur Müll raus...
Ich stehe gerade irgendwie voll auf dem Schlauch. :roll_eyes:

webworker

Welchen Teil genau? Das mit den Strichen und Punkten?

Hallo,

ja genau, den Teil. Also der:
14.8333 0.5 ??? 7.6 ???.? 0.0 ----.- ----.- ---.- ---.- ----.- 02.03.14 14:50

webworker

Das ist was anderes als nur einen Wert dieser Zeile. Dafür musst du einfach nur die Zeilen zählen. Am besten du fragst nicht auf \r ODER \n ab, sondern nur auf \n. Das zählst du mit und wenn es dreimal da war, hast du diese Zeile.

Wenn du die Zeile dann splitten willst um an die einzelnen Werte zu kommen, geht wahrscheinlich am einfachsten mit strtok() mit einem Leerzeichen als Delimiter:

http://www.cplusplus.com/reference/cstring/strtok/

Damit bekommt man Zeiger auf die Teil-Strings, die man weiter-verarbeiten kann. z.B. mit atof() in Floats wandeln. Jeder Aufruf liefert einen Zeiger auf den nächsten Teil-String. Das muss auch nicht unbedingt in einer while-Schleife sein wie bei den Beispielen da.

Was das am vernünftigsten ist hängt davon ab welche Werte du aus dem String herauspicken willst. Datum und Uhrzeit liest man am besten aus der ersten Zeile aus. Wobei der Code den ich oben hingeschrieben habe für "Uhrzeit: 14:20:55" ist. Das was du jetzt geschrieben hast ist was anderes! Dafür geht das nicht, bzw. man muss es etwas anpassen (d.h. die Indizes bei atoi() anders machen, oder den Format-String bei sscanf())

Und wie gesagt, das char Array muss dafür um einiges größer sein! Das muss groß genug für die gesamte Zeile sein.

Was sich hier auch anbietet ist das Problem aufzuteilen in das Einlesen von der seriellen Schnittstelle und der Verarbeitung. Letzteres kann man auch erst mal testen wenn man den String als Konstante vorgibt. Man muss nicht beides gleichzeitig machen. Den Teil kann man auch schön in Visual Studio C++ testen, da man da Debuggen kann.

Hallo,

danke für die hilfreiche Antwort. Das Auslesen der Zeile habe ich jetzt so gelöst, wie Du es beschrieben hast. Also einfach die "\n" zählen. So sieht der Test-Code aktuell aus:

#define STRLEN 300
char buffer[STRLEN];
int  bufferIndex = 0; 
int i;
void setup() {
  Serial.begin(9600);
}

void loop() {
   if (Serial.available()){
    char returned = Serial.read();
    if (returned == '\n'){
      i++;
    }
    if (returned != '\n' && i == 2){
      buffer[ bufferIndex++ ] = returned;
    }
    if (returned == '\n' && i == 3){
      buffer[ bufferIndex ] = 0;
      bufferIndex = 0;
    }
    if (i == 4){
      i = 0;
    }
  }
  Serial.println(buffer);
}

Würdet Ihr das auch so lösen, oder anders?

So ganz funktioniert es aber noch nicht, weil es wird mir "14.8333 0.5 ??? 7.6 ???.? 0.0 ----.- ----.- ---.- ---.- ----.- 02.031" zurückgegeben....

Das Zerlegen des Strings mach' ich auf dem Webserver mit PHP, da bin ich nämlich ein bisschen fitter. Außerdem wird der Adduino dadurch auch entlastet.

webworker

300 Byte ist etwas übertrieben. :slight_smile: Du brauchst Platz für diese Zeile. Nicht für den gesamten Datenstrom.

Sollte eigentlich gehen. Die letzte Zeile wird glaube ich auch aus dem Empfangspuffer ausgelesen. Wieso er das gerade an der Stelle abschneidet ist mir so jetzt nicht klar.

Das Serial.println() solltest du aber nur machen wenn der String ganz da ist. Also bei i == 3. Nicht in jedem loop() Durchlauf. Ich nehmen an du hast die Wetterstation an RX hängen? Das ist vielleicht nicht so gut, da da gleichzeitig die USB-Verbindung zum PC dran ist. Hier sind vielleicht zwei getrennte Schnittstellen besser. Wenn du keinen Mega hast (der 4 Hardware Schnittstellen hat, kannst du mit AltSoftSerial eine emulieren:
https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
Pins 8 und 9 auf dem UNO

Aber solche einfachen String Operationen sind für den Arduino eigentlich keine große Belastung. Manche der aufwendigeren Funktionen wie sprintf() und sscanf() fressen recht viel Flash, aber von der Rechenzeit ist es keine große Sache. Vieles davon ist nur Zeiger-Arithmetik und Vergleiche.
Aber das auf dem PC zu erledigen ist natürlich auch möglich.

Hey,

sorry für die verspätete Antwort - ich war bist jetzt auf Fehlersuche. Dazu aber gleich mehr!

Serenifly:
300 Byte ist etwas übertrieben. :slight_smile: Du brauchst Platz für diese Zeile. Nicht für den gesamten Datenstrom. [...]

Ich dachte: Sicher ist sicher. Hab's jetzt mal ein bisschen verkleinert.

Das Problem mit der abgehackten Zeile habe ich mittlerweile in den Griff bekommen. Ich zähle nämlich nicht nur die "\n" sondern auch die ersten Buchstaben. Das funktioniert jetzt perfekt.

Das mit dem zerlegen auf dem Webserver mit PHP wird doch nix, da der Arduino irgendwie keine Leerzeichen mit der "GET-Methode" übertragen kann...

Die Wetterstation hängt am RX und TX, da sie nur Daten sendet, wenn sie auch aufgefordert wird Daten zu schicken. Während der Programmierung nehme ich dann mein Selbstbau RS232-Shield ab. Wenn alles mal funktionieren würde, dann werde ich auf den Arduino MEGA umsteigen.
Von einer Software-Seriellen Schnittstelle habe ich abgesehen, da oft gesagt wird, dass diese sehr rechenintensiv sei und den Arduino manchmal in die Knie zwingt.

Am PC läuft mein ganzes Sketch nun perfekt nur an der Wetterstation zickt es gewaltig herum...
Das Sketch hat ja die Besonderheit, dass die Uhr am Arduino bei jedem Reset/ Neustart neu gestellt wird. Dazu wird an die Station ein Befehl geschickt, sodass sie danach die aktuelle Uhrzeit schickt. Der Arduino stellt dann brav seine Uhr. Also funktioniert die Kommunikation zwischen Arduino und Wetterstation.

Nur beim Anfordern der Wetterdaten gibt es Probleme. Der Befehl um Daten Anzufordern lautet: (STX)DS_DDMMYYHHMM_(ETX). DD, MM, ... müssen halt durch das aktuelle Datum bzw. Uhrzeit ersetzt werden. Also habe ich folgenden Code geschrieben (nur die wichtigsten Ausschnitte):

String STX = "\x02";
String ETX = "\x03";

long stamp = Day*100000000 + Month*1000000 + (Year%100)*10000 + Hour * 100 + Minute;
  String Stamp = String(stamp);

if (Day < 10){
    Serial.print(String(STX + "DS0" + Stamp + ETX));
    } else {
    Serial.print(String(STX + "DS" + Stamp + ETX));
    }
    delay(1000);

Leider schickt mir die Station nix! =(
Das funktioniert aber wieder problemlos:

    Serial.print(String(STX + "DS0503141530" + ETX));
    delay(1000);

Ich habe auch schon versucht alles nacheinander zu schicken - geht auch nicht.

webworker

PS: Ich hoffe jetzt mal, dass ihr mir das nicht übel nehmt, dass das hier schon ziemlich off Topic ist..... :blush:

long stamp = Day*100000000 + Month*1000000 + (Year%100)*10000

Damit erzeugst du dir wahrscheinlich einen Integer Überlauf. Standardmäßig wird in int gerechnet wenn sonst nichts dabei steht.

Du musst Variablen die nicht in einen int passen entweder auf unsigned long casten oder das machen:

long stamp = Day*100000000UL + Month*1000000UL + (Year%100)*10000UL

... und du musst dir mal sprintf ansehen, dann geht alles wie von selbst

const char STX = 2;
const char ETX = 3;

char msg[15];
sprintf(msg,"%cDS%02d%02d%02d%02d%02d%c",
                   STX, Day, Month, Year,  Hour, Minute, ETX );
Serial.print(msg);

(Statt msg kannst du natürlich auch deinen 300 byte buffer nehmen)

Ja, ich wollte halt nicht schon wieder sagen, dass die String Objekte Schrott sind :wink:

Noch besser ist übrigens sprintf_P:

#include <avr/pgmspace.h>

sprintf_P(msg, PSTR("%cDS%02d%02d%02d%02d%02d%c"), ....);

Spart das RAM für den Format String :slight_smile:

Irgendwie fehlt beides mal das "ETX-Endzeichen"?!

webworker:
Irgendwie fehlt beides mal das "ETX-Endzeichen"?!

?
Das STX ist aber da ???
Und bei Serial.write(msg) auch ???

Im SerialMonitor sind beide schlecht zu sehen...

Guten Abend,

ja, das STX ist da. Bei Serial.write(msg) fehlt das ETX auch. Im Serial Monitor werden die Zeichen ja als Kästchen dargestellt.
Deshalb müsste ja vor und nach dem Befehl ein Kästchen geben, es gibt aber nur eins davor.
Bei der Zeit funktioniert es lustigerweise :0 :0

Der komplette Code sieht so aus:

// Describtion:
// Sketch to receive weatherdata from the Thies DLx(Met)-Datalogger.
// The sketch uploads the weatherdata to your webserver in a MySQL-Database (e.g.).
// You can set the interval to recieve and send data in the variable runTime (in mins).
// The Arduino syncronize his clock with the datalogger at 12pm, 22pm and at the start
// of the Arduino. If you don't want this, set clockSync to 21 (off)!

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#define STRLEN 250
#define DATELEN 25
#define TIMELEN 25

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd (0x27, 20, 4);

int runTime = 10;    // intervall for the sketch

// ***** serial communication *****
String command;
float data[45];
char returned;
char buffer[STRLEN];
int  bufferIndex = 0;
int i,v,z;
const char STX = 2;
const char ETX = 3;
char msg[20];

// ***** explode the string from dlx *****
char delimiter[] = " ";
char *ptr;

// ***** clock-sync *****
char time[TIMELEN];
int  timeIndex = 0;
char date[DATELEN];
int  dateIndex = 0;
int clockSync = 0;    // synchronization for the clock
int dateSync = 1;      // synchronization date at start of the program
int h, m, s;

// ***** ethernet *****
byte mac[] = {0xDE,0xAD,0xBE,0xEF,0xFE,0xED};
char server[] = "****************";
IPAddress ip(192,168,2,100);
EthernetClient client;


void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  setTime(12,37,0,5,3,14);
  RTC.set(now());
  
  lcd.init();
}


void loop() {
  // ***** clock *****
  long Year = year();
  int Month = month();
  int Day = day();
  int Second = second();
  int Minute = minute();
  int Hour = hour();
  
  
  // ***** send commands to the datalogger *****
  if (Minute % runTime == 0 && Second == 30){
    // average
    i = 0;
    z = 0;
    sprintf_P(msg, PSTR("%cDS%02d%02d%02d%02d%02d%c"), STX, Day, Month, Year,  Hour, Minute, ETX );
    Serial.write(msg);
    delay(2000);
  }


  // ***** load the data from the logger into variables *****
  if (Serial.available() && clockSync > 20 && dateSync == 21){                                                                                                                                                                     
    char returned = Serial.read(); 
    if (returned != '\n' && returned != '\r'){ // Solange kein ende kommt...
      if (i == 0){
        i++; // einnmal erhöhen.
      }
      if (i == 2){ // jetzt müssen wir bei den werten sein...
        buffer[ bufferIndex++ ] = returned;
        z = 1;
      }
    } else {
      // jetzt muss das ende kommen...
      if (i == 1){
        i++;
      }
      if (i == 2 && z == 1){
        i++;
        lcd.setCursor(0,3);
        lcd.print(F("Abfrage!"));
        ptr = strtok(buffer, delimiter);
        v = 0;
        while(v != 43){
          data[v] = atof(ptr);
          ptr = strtok(NULL, delimiter);
          v++;
        }
      }
      // alles wieder auf anfang 
      buffer[ bufferIndex ] = 0;
      bufferIndex = 0;
    }
  }


  // ***** send the data to your webserver *****
  if (Minute % runTime == 0 && Second == 55){
    // average
    if (client.connect(server, 80)){
      client.print(F("GET /towebserver.php?"));
      client.print(F("windgeschw="));
      client.print(data[1]);
      client.print(F("&windrichtung="));
      client.print(data[2]);
      client.print(F("&temperatur1="));
      client.print(data[3]);
      client.print(F("&relfeuchte="));
      client.print(data[4]);
      client.print(F("&niederschlag="));
      client.print(data[5]);
      client.print(F("&luftdruck="));
      client.print(data[6]);
      client.print(F("&strahlung="));
      client.print(data[7]);
      client.print(F("&temperatur2="));
      client.print(data[8]);
      client.print(F("&20maeingang="));
      client.print(data[9]);
      client.print(F("&ereignisdauer="));
      client.print(data[10]);
      client.println(F("&id=****************' HTTP/1.1"));
      client.println(F("Host: **************"));
      client.println(F("Connection: close"));
      client.println();
      client.stop();
      delay(300);
    }
  }
  
  
  // ***** start the synchronization of the clock *****
  if (Hour == 12 && Minute == 15 && Second == 25 || Hour == 22 && Minute == 15 && Second == 25){
    clockSync = 0;
  }

  // ***** synchronization clock (time) *****
  if (clockSync == 0){
    sprintf_P(msg, PSTR("%cZZ%c"), STX, ETX );
    Serial.print(msg);
    delay(3000);
  }
  if (clockSync < 20){
    if (Serial.available()){
      char retTime = Serial.read();
      if (retTime == '\r'){
        time[ timeIndex ] = 0;
      }
      if (retTime == '\n'){
        time[ timeIndex ] = 0;
        timeIndex = 0;
      } else {
        time[ timeIndex++ ] = retTime;
      }
    }
    sscanf(time, "%*[^0-9]%d:%d:%d", &h, &m, &s);
    clockSync++;
  }
  
  // ***** send command to get date *****
  if (dateSync == 1 && clockSync == 20){
    sprintf_P(msg, PSTR("%cDD%c"), STX, ETX );
    Serial.print(msg);
    delay(3000);
  }
  if (dateSync >= 1 && dateSync < 21 && clockSync < 40 && clockSync >= 20){
    if (Serial.available()){
      char retDate = Serial.read();
      if (retDate == '\r'){
        date[ dateIndex ] = 0;
      }
      if (retDate == '\n'){
        date[ dateIndex ] = 0;
        dateIndex = 0;
      } else {
        date[ dateIndex++ ] = retDate;
      }
    }
    sscanf(date, "%*[^0-9]%d.%d.%d", &Day, &Month, &Year);
    dateSync++;
    clockSync++;
  }
  
  // ***** set time and date *****
  if (clockSync == 40 && dateSync == 21 || clockSync == 20 && dateSync == 21){
    clockSync++;
    setTime(h,m,s,Day,Month,Year);
    RTC.set(now());
    lcd.setCursor(0,2);
    lcd.print(F("Uhr gestellt!"));
  }
  lcd.setCursor(0,0);
  lcd.print(hour());
  lcd.print(F(":"));
  lcd.print(minute());
  lcd.print(F(":"));
  lcd.print(second());
  lcd.print(F("  "));
  lcd.print(day());
  lcd.print(F("."));
  lcd.print(month());
  lcd.setCursor(0,1);
  lcd.print(data[1]);
  lcd.print(F("  "));
  lcd.print(data[3]);
}

Falls es vielleicht hilfreich ist:
Bedienungsanleitung Datalogger DlxMet (Wetterstation)
Ab Seite 42 geht es um die Kommunikation über die Schnittstelle(n)

webworker

Wenn du einen String hast, dann solltest du Serial.print() verwenden. write() ist für Binär-Daten. Da kommt nicht unbedingt das gleiche raus.

Von sscanf() gibt es übrigens auch eine _P Version

Hiermit kannst du überprüfen wie viel RAM noch frei ist:

int getFreeRAM() 
{
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

webworker:
ja, das STX ist da. Bei Serial.write(msg) fehlt das ETX auch. Im Serial Monitor werden die Zeichen ja als Kästchen dargestellt.
Deshalb müsste ja vor und nach dem Befehl ein Kästchen geben, es gibt aber nur eins davor.
Bei der Zeit funktioniert es lustigerweise

const char STX = 2;

const char ETX = 3;
char msg[20];
void loop() {

sprintf_P(msg, PSTR("%cDS%02d%02d%02d%02d%02d%c"), STX, Day, Month, Year,  Hour, Minute, ETX );
   Serial.write(msg);
   delay(2000);
// ...
 if (clockSync == 0){
   sprintf_P(msg, PSTR("%cZZ%c"), STX, ETX );
   Serial.print(msg);
   delay(3000);
 }
 // ***** send command to get date *****
 if (dateSync == 1 && clockSync == 20){
   sprintf_P(msg, PSTR("%cDD%c"), STX, ETX );
   Serial.print(msg);
   delay(3000);
 }
}

Ich seh erstmal keinen wesentlichen Unterschied der 3 Ausgaben.
Ob STX und ETX beide ein Kästchen im SerialMonitor erzeugen, weiss ich nicht.

Serial.write(STX); Serial.print(F("DD")); Serial.write(ETX);

geht übrigens genausogut wie

    sprintf_P(msg, PSTR("%cDD%c"), STX, ETX );
    Serial.print(msg);

Hallo,

scheinbar funktioniert jetzt das Abholen und Empfangen der Wetterdaten.
Das Problem war gar nicht der Befehl, sondern einfach das Empfangen. Aus welchem Grund auch immer, hat das Empfangen am PC problemlos funktioniert, aber am Datalogger nicht.
Mein Projekt möchte ich hier im Forum noch vorstellen und dort werde ich dann auch meinen Code veröffentlichen.

So wie es im Moment aussieht, ist der UNO jetzt aber schon ausgelastet. Denn es werden nur 1x nach dem Start Werte auf den Webserver übertragen. Am Display aktualisieren sich die Messwerte aber...
Ich habe mir aber einen MEGA bestellt und wenn der dann ankommt teste ich alles mal an diesem.

Ich möchte mich nochmals für Eure super Hilfe bedanken.
Ich glaube ohne Euch wäre ich schon lange verzweifelt.

webworker