Werte über Serielle Schnittschelle empfangen und im WebIf Anzeigen

Hallo ,
wenn ich das richtig sehe liest Du von der Seriellen immer bist zu dem Endzeichen ein. Damit hast Du in der Zeichenkette receivedChars auch nur je eine Zeile drin.
Danach kommst Du aus der schleife raus , und halt wieder rein weil immer noch Zeichen nicht ausgelesen sind, aber dann wird die Zeichenkette neu vom Anfang gefüllt. Du musst alles in eine Variable schreiben, eventuell benötigst Du dazu eine andre Endkennung.
Der ascii Zeichensatz bietet für sowas historisch bedingt STX und ETX an. Dazu musst Du aber den Sender schon ändern. Andere Variante Du hast für jede Zeile eine Zeichenkette, dann musst du die Zeilen allerdings mitzählen.
Irgendwie ist Dein Konzept aber auch suboptimal :wink:
Heinz

Er muss sogar wissen was tatsächlich kommt! Denn er kann - ausgehend von seinem Ursprung - nicht garantieren, was drin steht.
20 übertragene Werte sind nicht 20 Strings. :slight_smile:

Ja, es wird ein 2 Arduino genutzt, weil ich keine Steckplätze mehr frei habe und auch nicht (aus Platzgrunden) auf z.B. einen Mega gehen kann. Wie du am Sketch von der Sonnenverfolgung sehen kannst ist der UNO voll belegt...Desweiteren wird der 2.Uno an einem anderen Ort eingebaut, wo ich auch Netzwerk habe. Außerdem möchte ich später mal eine weitere Sonnenverfolgung bauen, dafür wird dann auch der 2. Arduino genutzt :wink:

Hintergrund mit der Webseite es jetzt schon zu machen ist, damit man die Daten immer mal wieder prüfen kann, ohne das man mit einem Laptop/Tablet auf die Garage muss. So kann man dann auch z.B. bei einem defekt vom LDR, was ich leider nach und nach hatte schneller reagieren und prüfen, warum etwas nicht Funktioniert.

PS.: War halt mein 1.Projekt, wusste nicht das ich soviele Pine benötige. Hat sich ja nach und nach entwickelt.

Das halte ich für gewagt... :wink:

Aber bedenke!
Wenn Du die Serielle Kommunikation benutzt, ist Deine Kabellänge ein entscheidendes Kriterium!

Also...
Wenn Du Deine Daten tatsächlich mit dem UNO senden willst:
Dann in jeder Zeile eine Kennung. Die wird auf der anderen Seite ausgewertet.
Und je nach Kennung wird eine Variable - von mir aus auch als String - gefüllt.
Die Ausgabe geht dann ganz easy.

1 Like

Wusste garnicht, das es auch so kleine Mega gibt...aber das Ethernetshield sprengt den Rahmen :wink:

Wie Lang dürfte den mach deinen Erfahrungen die Kabellänge so sein?

Mit der Kennung meinst du z.B.:

18:57:04.881 -> 1. LDRol:0 LDRor:0
18:57:04.881 -> 2. LDRul:0 LDRur:0
18:57:04.935 -> 3. LDRol2:0 LDRor2:0
18:57:04.935 -> 4. GWO:0 GWU:0
18:57:04.935 -> 5. GWL:0 GWR:0

Yes!

Gibt es auch in klein.
UND! Das hat mehr Sockets für gleichzeitige Verbindungen!

1 Like

Ist ja sehr interresant wie klein es alles geht.

Aber ich möchte später auch mal eine Amperezange und eine Voltmessung mit einbauen.

Wo?

Es soll später wenn es mit der Webseite läuft an den 2. Arduino angeschlossen werden. Und da hätte ich auch dann die Möglichkeit, wenn der Uno zu klein wird einen Mega zu nehmen.

Aber welche Hardware dafür genutzt werden soll oder ihr empfehlen könnt kommt dann!

OK!
Dann sind wir ja schon fast beieinander...
Nehmen wir mal an, es gäbe ein kleines Controllerboard OHNE USB-Schnittstelle, aber sonst mit allem was Du hast.
Dieses Board hat zwei zusätzliche Analogpins - (nur Analog IN!) - aber du bekämst damit 2 reguläre Pins frei.
Diese 2 Pins kannst Du dann verwenden um eine Kommunikationsschnittstelle aufzumachen. Wäre hier RS485.

Dann brauchst Dir auch nicht (unbedingt) Gedanken machen um Leitungslänge.

Board: Arduino Pro Mini - Erweiterung mit RS485
und alles schick :slight_smile:

1 Like

Das Abspeichern in Variablen wurde ja schon angesprochen.

Man kann eine HTML-Seite aber auch wie den seriellen Monitor verwenden, indem immer die neue Zeile unten angehängt wird. Dazu habe ich mein Programm aus #9 abgewandelt:

// getestet mit ESP32
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include "zugangsdaten.h"
const char * sta_ssid     = STA_SSID;      // << kann bis zu 32 Zeichen haben
const char * sta_password = STA_PASSWORD;  // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen

WebServer server(80);

const int led = 13;
const byte maxChars = 40;
char receivedChars[maxChars] = {'\0'};
char text[5][40] = { {"T0"}, {"T1"}, {"T2"}, {"T3"}, {"T4"} };

void handleRoot() {
  server.send(200, "text/plain", "hello from esp32!");
}

void handleNotFound() {
  server.send(404, "text/plain", "File Not Found\n\n");
}

void handleTest() {
  char temp[700];
  snprintf(temp, sizeof temp, R"(<!DOCTYPE html>
<HTML><HEAD><meta http-equiv="refresh" content="1"><TITLE>PV Anlage</TITLE>
<meta charset = 'utf-8'>
</HEAD><BODY>
 <h2 align=center><font size=7><b>PV Anlage</b></font></h2>
%s<br>%s<br>%s<br>%s<br>%s
</BODY></HTML>)", text[0], text[1], text[2], text[3], text[4] );
  server.send(200, "text/html", temp);
}

void setup(void) {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(sta_ssid, sta_password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(sta_ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/test", handleTest);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");
}

void loop(void) {
  server.handleClient();
  recvWithEndMarker();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  const char endMarker = '\n';
  char rc;

  if (Serial.available() > 0) {
    rc = Serial.read();

    if (rc != endMarker) {
      if (ndx < maxChars - 1) {
        receivedChars[ndx] = rc;
        ndx++;
        receivedChars[ndx] = '\0';
      }
    } else {
      Serial.println(receivedChars);
      ndx = 0;
      strncpy ( text[0], text[1], sizeof(text[0]) );
      strncpy ( text[1], text[2], sizeof(text[0]) );
      strncpy ( text[2], text[3], sizeof(text[0]) );
      strncpy ( text[3], text[4], sizeof(text[0]) );
      strncpy ( text[4], receivedChars, sizeof(text[0]) );
    }
  }
}

Beim UNO mußt Du den begrenzten Speicher berücksichtigen.

1 Like

Ich habe jetzt mal weiter gemacht den Sketch anzupassen. Bekomme aber diese Fehlermeldung:

'class EthernetServer' has no member named 'handleClient'

Der Sketch sieht jetzt so aus:

// Kommunikation mit anderen Arduino
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

//Ethernet Shield
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x00, 0x10, 0xFA, 0x6E, 0x28, 0x4A }; // MAC Adresse des Arduino Boards

EthernetServer server(80); // Port Einstellung (Standard für HTML : 80)

// Speicher
const byte maxChars = 40;
char receivedChars[maxChars] = {'\0'};
char text[5][40] = { {"T0"}, {"T1"}, {"T2"}, {"T3"}, {"T4"} };

void handleRoot() {
  server.print("HTTP/1.1 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
}

void handleNotFound() {
  server.print("HTTP/1.1 400 OK\r\nServer: arduino\r\nContent-Type: Error/html\r\n\r\n");
}

void handleTest() {
  char temp[700];
  snprintf(temp, sizeof temp, R"(<!DOCTYPE html>
<HTML><HEAD><meta http-equiv="refresh" content="1"><TITLE>PV Anlage</TITLE>
<meta charset = 'utf-8'>
</HEAD><BODY>
 <h2 align=center><font size=7><b>PV Anlage</b></font></h2>
%s<br>%s<br>%s<br>%s<br>%s
</BODY></HTML>)", text[0], text[1], text[2], text[3], text[4] );
  server.print("HTTP/1.1 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
}

void setup()
{
  Ethernet.begin(mac); // Ethernet initialisieren
  server.begin(); // Auf Clients warten
  Serial.print("Arduino's IP Address: ");
  Serial.println(Ethernet.localIP());

  Serial.print("DNS Server's IP Address: ");
  Serial.println(Ethernet.dnsServerIP());

  Serial.print("Gateway's IP Address: ");
  Serial.println(Ethernet.gatewayIP());

  Serial.print("Network's Subnet Mask: ");
  Serial.println(Ethernet.subnetMask());

  Serial.begin(9600); // Serielle Schnittstelle initialisieren

  mySerial.begin(115200); // Kommunikation mit dem anderen Arduino
}

void loop()
{
  // Lesen und Schreiben der Seriellen Schnittstelle
  if (mySerial.available())
  {
    Serial.write(mySerial.read());
  }
  if (Serial.available())
  {
    mySerial.write(Serial.read());
  }

  {
    server.handleClient();
    recvWithEndMarker();
  }

  void recvWithEndMarker() {
    static byte ndx = 0;
    const char endMarker = '\n';
    char rc;

    if (Serial.available() > 0)
    {
      rc = Serial.read();

      if (rc != endMarker)
      {
        if (ndx < maxChars - 1) {
          receivedChars[ndx] = rc;
          ndx++;
          receivedChars[ndx] = '\0';
        }
      }
      else
      {
        Serial.println(receivedChars);
        ndx = 0;
        strncpy ( text[0], text[1], sizeof(text[0]) );
        strncpy ( text[1], text[2], sizeof(text[0]) );
        strncpy ( text[2], text[3], sizeof(text[0]) );
        strncpy ( text[3], text[4], sizeof(text[0]) );
        strncpy ( text[4], receivedChars, sizeof(text[0]) );
      }
    }
  }

Wie muss die Zeile für die Ethernet Schnittstelle lauten?

rein informativ: Der Code kann nicht kompilieren
Klammerfehler.

server.handleClient() ... ESP?

1 Like

Habe es jetzt mal übersichtlicher gemacht:

// Kommunikation mit anderen Arduino
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

//Ethernet Shield
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x00, 0x10, 0xFA, 0x6E, 0x28, 0x4A }; // MAC Adresse des Arduino Boards

EthernetServer server(80); // Port Einstellung (Standard für HTML : 80)

// Speicher
const byte maxChars = 40;
char receivedChars[maxChars] = {'\0'};
char text[5][40] = { {"T0"}, {"T1"}, {"T2"}, {"T3"}, {"T4"} };

void handleRoot()
{
  server.print("HTTP/1.1 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
}

void handleNotFound()
{
  server.print("HTTP/1.1 400 OK\r\nServer: arduino\r\nContent-Type: Error/html\r\n\r\n");
}

void handleTest()
{
  char temp[700];
  snprintf(temp, sizeof temp, R"(<!DOCTYPE html>
<HTML><HEAD><meta http-equiv="refresh" content="1"><TITLE>PV Anlage</TITLE>
<meta charset = 'utf-8'>
</HEAD><BODY>
 <h2 align=center><font size=7><b>PV Anlage</b></font></h2>
%s<br>%s<br>%s<br>%s<br>%s
</BODY></HTML>)", text[0], text[1], text[2], text[3], text[4] );
  server.print("HTTP/1.1 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
}

void setup()
{
  Ethernet.begin(mac); // Ethernet initialisieren
  server.begin(); // Auf Clients warten
  Serial.print("Arduino's IP Address: ");
  Serial.println(Ethernet.localIP());

  Serial.print("DNS Server's IP Address: ");
  Serial.println(Ethernet.dnsServerIP());

  Serial.print("Gateway's IP Address: ");
  Serial.println(Ethernet.gatewayIP());

  Serial.print("Network's Subnet Mask: ");
  Serial.println(Ethernet.subnetMask());

  Serial.begin(9600); // Serielle Schnittstelle initialisieren

  mySerial.begin(115200); // Kommunikation mit dem anderen Arduino
}

void loop()
{
  // Lesen und Schreiben der Seriellen Schnittstelle
  if (mySerial.available())
  {
    Serial.write(mySerial.read());
  }
  if (Serial.available())
  {
    mySerial.write(Serial.read());
  }

  {
    server.handleClient();
    recvWithEndMarker();
  }

  void recvWithEndMarker()
  {
    static byte ndx = 0;
    const char endMarker = '\n';
    char rc;
  }

  if (Serial.available() > 0)
  {
    rc = Serial.read();

    if (rc != endMarker)
    {
      if (ndx < maxChars - 1)
      {
        receivedChars[ndx] = rc;
        ndx++;
        receivedChars[ndx] = '\0';
      }
    }
    else
    {
      Serial.println(receivedChars);
      ndx = 0;
      strncpy ( text[0], text[1], sizeof(text[0]) );
      strncpy ( text[1], text[2], sizeof(text[0]) );
      strncpy ( text[2], text[3], sizeof(text[0]) );
      strncpy ( text[3], text[4], sizeof(text[0]) );
      strncpy ( text[4], receivedChars, sizeof(text[0]) );
    }
  }
}

Und den Fehler von deinem Hinweis angepasst!

Nein, Ethernet Shield W5100

Die ethernet.lib kennt kein .handleClient().
Halte Dich an das Beispiel des Webservers aus den mitgelieferten Beispielen.

1 Like

... oder vor 3 Monaten (!) gabs in Beitrag #10 auch schon einen funktionierenden webserver...

Der ist auch nicht ganz richtig, da Fehlt der Bereich zum lesen der Serielle Schnittstelle im Loop:

  if (mySerial.available())
  {
    Serial.write(mySerial.read());
  }
  if (Serial.available())
  {
    mySerial.write(Serial.read());
  }

Ich habe jetzt mal wieder weiter gemacht, aktuell sieht es so aus:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX

//Ethernet Shield
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x00, 0x10, 0xFA, 0x6E, 0x28, 0x4A }; // MAC Adresse des Arduino Boards

EthernetServer server(80); // Port Einstellung (Standard für HTML : 80)

const byte maxChars = 50;
char receivedChars[maxChars] = {'\0'};
char text[5][40] = { {"T0"}, {"T1"}, {"T2"}, {"T3"}, {"T4"} };

void recvWithEndMarker() {
  static byte ndx = 0;
  const char endMarker = '\n';
  char rc;

  if (Serial.available() > 0) {
    rc = Serial.read();

    if (rc != endMarker) {
      if (ndx < maxChars - 1) {
        receivedChars[ndx] = rc;
        ndx++;
        receivedChars[ndx] = '\0';
      }
    } else {
      Serial.println(receivedChars);
      ndx = 0;
      strncpy ( text[0], text[1], sizeof(text[0]) );
      strncpy ( text[1], text[2], sizeof(text[0]) );
      strncpy ( text[2], text[3], sizeof(text[0]) );
      strncpy ( text[3], text[4], sizeof(text[0]) );
      strncpy ( text[4], receivedChars, sizeof(text[0]) );
    }
  }
}

void checkClient()
{
  EthernetClient client = server.available(); //Prüfen, ob Client Seite aufruft
  if (client)
  { // Seitenaufruf durch User
    // Ausgabe in HTML
    server.print("HTTP/1.0 200 OK\r\n"  // kein content lenght --> dann nur HTTP/1.0!
                 "Server: arduino\r\n"
                 "Content-Type: text/html\r\n\r\n"
                 "<!doctype html>\n"
                 "<html lang='de'>\n"
                 "<head>\n"
                 "<meta charset='utf-8'>\n"
                 "<title>PV Anlage</title>\n"
                 "<style>\n"
                 "h2, p{text-align:center}\n"
                 "h2{font-size:7em;font-weight:bold}\n" // todo: Einheit prüfen, hab einfach em genommen
                 "</style>\n"
                 "</head>\n"
                 "<body>\n"
                 "<h2>PV Anlage</h2>\n"
                 "<p>");
    server.print (text[0], text[1], text[2], text[3], text[4]); // //Hier soll dann die Daten ausgegeben werden!
    server.print ("</p>\n"
                  "</body>\n"
                  "</html>");
    //delay(500); // Kurzer Delay, um Daten zu senden - ob das notwendig ist hm...
    client.stop(); // Verbindung mit dem Client trennen
  }
}

void setup()
{
  Serial.begin(9600); // Serielle Schnittstelle initialisieren
  mySerial.begin(9600); // Kommunikation mit dem anderen Arduino
  Ethernet.begin(mac); // Ethernet initialisieren
  server.begin();      // Server starten
  Serial.print(F("Arduino's IP Address: "));
  Serial.println(Ethernet.localIP());
  Serial.print(F("DNS Server's IP Address: "));
  Serial.println(Ethernet.dnsServerIP());
  Serial.print(F("Gateway's IP Address: "));
  Serial.println(Ethernet.gatewayIP());
  Serial.print(F("Network's Subnet Mask: "));
  Serial.println(Ethernet.subnetMask());
}

void loop()
{
  if (mySerial.available())
  {
    Serial.write(mySerial.read());
  }
  if (Serial.available())
  {
    mySerial.write(Serial.read());
  }
  checkClient();
  recvWithEndMarker();
}

Jetzt habe ich noch das Problem mit der Fehlermeldung beim Komplimieren:

no matching function for call to 'EthernetServer::print(char [40], char [40], char [40], char [40], char [40])'

Liegt an dieser Zeile:

server.print (text[0], text[1], text[2], text[3], text[4]); // //Hier soll dann die Daten ausgegeben werden!

Wie muss ich die Auslesen, damit mir die Daten Angezeigt werden? :thinking:

PS.: Die Serielle Kommunikation funktioniert. Ich bekomme die Daten vom 1. Arduino auf dem 2. und dort per Seriellen Monitor auch angezeigt!

Versuch mal:

void checkClient()
{
  EthernetClient client = server.available(); //Prüfen, ob Client Seite aufruft
  if (client)
  {
    // Seitenaufruf durch User
    // Ausgabe in HTML
    server.print("HTTP/1.0 200 OK\r\n"  // kein content lenght --> dann nur HTTP/1.0!
                 "Server: arduino\r\n"
                 "Content-Type: text/html\r\n\r\n"
                 "<!doctype html>\n"
                 "<html lang='de'>\n"
                 "<head>\n"
                 "<meta charset='utf-8'>\n"
                 "<title>PV Anlage</title>\n"
                 "<style>\n"
                 "h2, p{text-align:center}\n"
                 "h2{font-size:7em;font-weight:bold}\n" // todo: Einheit prüfen, hab einfach em genommen
                 "</style>\n"
                 "</head>\n"
                 "<body>\n"
                 "<h2>PV Anlage</h2>\n"
                 "<p>");
    for (byte b = 0; b < sizeof(text) / sizeof(text[0]); b++)
    {
      server.print (text[b]); // //Hier soll dann die Daten ausgegeben werden!
      server.print(", ");
    }
    server.print ("</p>\n"
                  "</body>\n"
                  "</html>");
    //delay(500); // Kurzer Delay, um Daten zu senden - ob das notwendig ist hm...
    client.stop(); // Verbindung mit dem Client trennen
  }
}
1 Like

Dann kommt als Ausgabe beim Seitenaufruf der Body " PV Anlage" und als "Werte" nur "T0, T1, T2, T3, T4, "

das steht auch in deinen Variablen. Die Ausgabe ist daher korrekt.

Auch macht es wenig Sinn mySerial im loop auszulesen und auszugeben - denn dann steht für's lesen in recvWithEndMarker() nichts mehr im Empfangsbuffer.