Werte über Serielle Schnittschelle empfangen und im WebIf Anzeigen

Hallo,
ich möchte gerne Daten von einem anderen Arduino empfangen und im WebIf anzeigen lassen.
Ich habe die kommunikation vom Arduino zum anderen Arduino und die USB Ausgabe schonmal am laufen. Und das WebIf läuft auch schonmal. Jetzt möchte ich gerne das ich die Daten, die Empfangen werden über das WebIf Ausgeben. Muss ich die Daten erst speichern für die Ausgabe? Oder kann man die Daten lesen und die "passenden" Zeile raussuchen entsprechend Ausgeben?

Hier mal erstmal der Sketch:

// 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)

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(9600); // 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());
  }

  EthernetClient client = server.available(); //Prüfen, ob Client Seite aufruft
  if (client)
  { // Seitenaufruf durch User
    // Ausgabe in HTML
    server.print("HTTP/1.1 200 OK\r\nServer: arduino\r\nContent-Type: text/html\r\n\r\n");
    server.print("<HTML><HEAD><TITLE>");
    server.print("PV Anlage");
    server.print("</TITLE>");
    server.print("<meta charset = 'utf-8'>");
    server.print("</HEAD><BODY>");
    server.print("<h2 align=center><font size=7><b>PV Anlage</b></font></h2>");
//Hier soll dann die Daten ausgegeben werden!
    delay(500); // Kurzer Delay, um Daten zu senden
    client.stop(); // Verbindung mit dem Client trennen
  }
}

Was verstehst du unter "WebIf" ?

Setze konstante Zeichenketten ins F-Macro
server.print(F("PV Anlage"));
da verbrauchen sie keinen RAM.
Welchen Arduino benutzt Du?

Ich würde die seriell empfangenen Werte in Variablen abspeichern, damit der Webserver darauf zugreifen kann, wenn die Seite abgerufen wird. Es genügen ja Zeichenketten (char-Array), da Du mit den Daten nicht rechnen willst.
Dann musst Du Dir nur noch Gedanken machen, was Du nach dem Abrufen machst - leeren oder alten Wert stehen lassen.

Gruß Tommy

1 Like

Ich möchte dafür einen Arduino Uno R3 und das Ethernet Shield W 5100 nutzen

Es soll nur ein kleines WebIf (also eine Internetseite) werden, zur Ausgabe der Daten ohne schnick schnack...

Na, dann mach das doch einfach. Der Anfang war doch schon mal nicht schlecht. Das HTML abschließen nicht vergessen.
Mehr kann man zu dem Fragment nicht sagen.

Gruß Tommy

ja sonst kannst du sie nicht ausgeben wenn sie später vom Browser angefordert werden.

sonst schon, aber beim Ethernet Server nicht einfach das F-Makro verwenden.

Wenn dann in Verbindung mit der Streamlib, dann ja.
https://werner.rothschopf.net/microcontroller/202011_arduino_webserver_optimieren.htm

Danke für die Info.

Gruß Tommy

Könnte "Webinterface" bedeuten.

Deine Hardware habe ich leider nicht, daher nutze ich einen ESP32.

Kommen neue Daten über die serielle Schnittstelle, dann werden diese in receivedChars gespeichert. Fordert der Client die HTML-Seite an, wird receivedChars zusammen mit dem festen HTML-Text an den Client geschickt:

// getestet mit ESP32
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include "zugangsdaten.h"

WebServer server(80);

const int led = 13;
const byte maxChars = 50;
char receivedChars[maxChars] = {'\0'};

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><TITLE>PV Anlage</TITLE>
<meta charset = 'utf-8'>
</HEAD><BODY>
 <h2 align=center><font size=7><b>PV Anlage</b></font></h2>
%s
</BODY></HTML>)", receivedChars);
  server.send(200, "text/html", temp);
}

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

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(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;
    }
  }
}

grafik

Ich hoffe, es nützt Dir irgendwie :slightly_smiling_face:

kein Beispiel zum Speichersparen *), aber trotzdem ein wenig vorsichtiger:

//https://forum.arduino.cc/t/werte-uber-serielle-schnittschelle-empfangen-und-im-webif-anzeigen/947381/9

// Kommunikation mit anderen Arduino
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
//HardwareSerial &mySerial = Serial;    // HW Serial zum schnellen Testen

//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'};

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

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

    if (rc != endMarker) {
      if (ndx < maxChars - 1) {
        receivedChars[ndx] = rc;
        ndx++;
        receivedChars[ndx] = '\0';
      }
    } else {
      Serial.println(receivedChars);
      ndx = 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 (receivedChars); // //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
  Serial.println(F("nicht mehr als ein Prototyp"));
  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()
{
  checkClient();
  recvWithEndMarker();
}

trotz "Speichersparen" sollte man sich während der Entwicklung ein paar Zeilenschritte im HTML leisten, das macht den Quelltext zum debuggen lesbarer.

apropos HTML: das soll man prüfen mit einem Validator:
hier kann man es einfach mit copy paste einfügen:

https://validator.w3.org/nu/#textarea

Man kann den Validator auch lokal in den Browser einbinden, dann bekommt man die Fehler gleich beim Anschauen angezeigt.

Gruß Tommy

übrigens,
das delay(500) vor dem client.stop() bewirkt vor allem, dass das ganze langsam wird:
es kommen 500ms einfach on top dazu:


ein yield, ein delay(1) von mir aus aber keine 500!

ohne delay, alles im SRAM:
16ms (mein Läppi hängt im wifi).

und extra noch mal als Demo, was passiert, wenn mans ins F-Makro gibt:
um die 100ms

Danke agmue.
Warum verwendet der TO nur derartige unbekannte Begriffe / Abkürzungen ?
Wir können doch hier klare Beschreibungen nutzen.

Diese rhetorische Frage ließe sich beantworten, wenn man ihn kennen würde, was nicht der Fall ist.