Telnet2Serial – Telnet zu RS232/Seriell Brücke (Remote Console) mit dem ESP8266 Microcontroller

Wie bringt man eigentlich ein Arduino Projekt oder irgendein Gerät mit seriellem Interface möglicht einfach ins WLAN? – Diese Frage ging mit durch den Kopf, als ich über eine Verbesserung meines Codeschlossprojekts nachdachte. Dabei bin ich auf die Idee gekommen eine Telnet zu Seriell Brücke mit dem ESP8266 zu bauen.

Im Netz habe ich einige Hinweise und Codes gefunden, die einen Ansatz bildeten, aber eine komplette Lösung. Die hier vorgestellte Lösung ist für die Arduino IDE geeignet, wenn man sie für den ESP8266 Mikrocontroller erweitert.

Als Adapterplatine kann man diese Programmierplatine für den ESP8266 verwenden (klick – die Taster kann man natürlich weglassen).
esp8266 progboard
Der Anschluss ist hier analog zu den typischen USB/Seriell Adaptern gestaltet: Pin2 an RX, Pin3 an TX, Pin4 an eine Spannungsversorgung (5-12V), Pin5 an Masse.

Man muss mit den Pegeln an seriellen Schnittstellen vorsichtig sein. Der ESP8266 läuft mit 3,3V. Die Programmierplatine ist für den Anschluss an einen Arduino geeignet und wandelt den Pegel per Spannungsteiler von 5V auf 3,3V. Die Schaltung passt auch auf die meisten Logikboards. Generell können serielle Schnittstellen das Signal mit bis zu +-12V darstellen. In diesem Fall muss man zu einem aufwändigeren Pegelwandler greifen.

Der Code erlaubt bis zu 5 parallele Klienten. Diese Klienten können alle parallel lesend und schreibend zugreifen. Der Adapter trägt allerdings keine Sorge, dass die Klienten nicht parallel schreiben und dann sinnlose Eingaben entstehen. Dafür müßt ihr in der jeweiligen Anwendung selbst sorgen (oder die Anzahl die Klienten auf 1 runtersetzen).

Im Code können am Anfang einige Einstellungen konfiguiert werden; u.a. welche Geschwindigkeit der seriellen Schnittstelle oder ob der Adapter als Accesspoint laufen soll oder sich in ein bestehendes WLAN verbinden soll.
// max number of clients that can connect
#define MAX_NO_CLIENTS 5
const WiFiMode wifi_mode = WIFI_AP; // set WIFI_AP for access-point or WIFI_STA for WIFI client
const char* ssid = "T2S-Accesspoint"; // Name of AP (for WIFI_AP) or name of Wifi to connect to (for WIFI_STA)
const char* password = "12345678"; // set to "" for open access point w/o password
const int iSerialSpeed = 9600; // speed of the serial connection
const bool bSuppressLocalEcho = true; // shall local echo in telnet be suppressed (usually yes)

Die Einstellungen sollten weitestgehend selbsterklärend sein. Falls nicht, dann fragt gerne. Der Code versucht den Telnet Client so zu konfigurieren, dass Telnet keine lokalen Echos (Kopien) der Eingaben anzeigt. Das führt typischerweise dazu, dass jede Taste doppelt angezeigt wird. Dies erscheint aber nur so. Die Unterdrückung funktioniert nicht mit jedem Telnet Programm. Beim Windows Telnet Programm klappt es. Bei putty nicht; da kann man es aber in den Einstellungen konfigurieren.

Hier gibt es den Code: ESP_Telnet2Serial

Hier nun ein Beispiel bei der ich den ESP8266 als Telnet2Serial Brücke an einen Arduino angeschlossen habe (TX und RX); in diesem Beispiel habe ich auf dem Arduino das Codeschlossprogramm genommen.
Telnet2Serial

24 Gedanken zu „Telnet2Serial – Telnet zu RS232/Seriell Brücke (Remote Console) mit dem ESP8266 Microcontroller

  1. Folkmar

    Hallo,
    Hat alles sehr gut geklappt. Danke dafür.
    Aber mit einer neuen Installation von der Arduino IDE 1.6.8 funktioniert es nicht mehr.
    Vielleicht findest Du den Fehler?
    Fehlermeldung:
    Exception (2):
    epc1=0x3ffe84b8 epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffe84b8 depc=0x00000000

    ctx: sys
    sp: 3ffffc90 end: 3fffffb0 offset: 01a0

    >>>stack>>>
    3ffffe30: 40211601 3ffffed0 3ffed620 3ffed00c
    3ffffe40: 40211661 3ffffed0 40211549 3ffffed0
    3ffffe5
    .
    .
    .
    3ffee448 3fffdad0 3ffeed2c 402036ab
    3fffffa0: 40000f49 40000f49 3fffdab0 40000f49
    <<<stack<<<

    ets Jan 8 2013,rst cause:1, boot mode:(3,6)

    load 0x4010f000, len 1264, room 16
    tail 0
    chksum 0x42
    csum 0x42

    Antworten
    1. ST Beitragsautor

      Prima, dass der Code geht. Das beschriebene Problem dürfte mit der Arduino IDE Version und der Esp Erweiterung zusammenhängen. Entweder gehst Du zurück auf die 1.6.4 oder wartest, bis das Problem von der Esp Seite gelöst wird.
      Gruss Stefan

      Antworten
  2. Kabumdada

    Hallo Stefan,

    ich hab das ganze jetzt mal ausprobiert indem ich mir das Programm geladen hab und komm jetzt einfach nicht weiter.
    Habe zuerst probiert das Prog. normal wie immer zu übertragen.
    Werkzeuge -> Board -> Arduino Nano
    Dabei kam die Fehlermeldung das das Prog. nicht kompatibel ist.
    Also hab ich wie hier beschrieben das ESP8266 eingebunden und unter Werkzeuge->Board->Generic ESP8266 Modul ausgewählt.
    Dabei bekomm ich nun diese Fehlermeldungen:

    warning: espcomm_sync failed
    error: espcomm_open failed
    error: espcomm_upload_mem failed

    Was muss ich tun, bzw wie muss ich den Code anpassen damit ich das ganze mit dem Pretzelboard (NanoESP) verwenden kann? Es hat ja eigentlich schon ein integriertes WLan Modul.

    Vielen Dank im Voraus.
    Marcel

    Antworten
    1. ST Beitragsautor

      Hi Kabumdada,

      das Prezeboard ist eine Kombination aus einem Arduino Nano und einem ESP8266. Kann man für 30€ fertig kaufen oder selbst für ca. 5 Euro bauen. Das Prezelboard wird so ausgeliefert, dass auf dem ESP8266 die AT Firmware läuft. So wie das Board aufgebaut ist, kommst Du per USB nur an den Arduino dran und nur diesen kannst Du programmieren. Deshalb mal ich das Pretzelboard auch nicht so arg – teuer und im Detail nicht gut gemacht.
      Du bekommst also die Fehlermeldungen, weil Du versuchst, ein ESP Board zu proggen aber einen Arduino dran hast. Wenn Du den ESP auf dem Prezelboard direkt programmieren willst, dann musst Du den 8-poligen Stecker neben dem ESP einlöten und einen ESP Programmieradapter nehmen/bauen. Siehe z.B. hier:
      https://blog.thesen.eu/esp8266-wlan-microcontroller-mit-der-arduino-ide-programmieren/
      Die Kommunikation zwischen ESP und Arduino machst Du per serieller Kommunikation. Die Markisensteuering hier im Blog macht das z.B. so.

      Noch ein Hinweis: Wenn Du dann den ESP Teil wie einen normalen ESP programmierst, funktionieren die normalen Pretzelboard Beispiele nicht mehr. Es gibt aber Möglickeiten, wieder eine AT Firmware auf den ESP zu flashen. Da musst Du ggf mal googeln.

      Viel Erfolg!

      Gruss Stefan

      P.S.: Oder Du bleibst bei der AT Firmware auf dem ESP. Das ist allerdings eher unschön von der Arduino Seite her zu programmieren (Stringparsing über Stringparsing) und am Ende nicht wirklich stabil zu bekommen, weil Du z.B. nicht einfach herausfinden kannst, ob die WLAN Verbindung neu aufgebaut werden muss.
      P.P.S.: oder Du schaffst es, alle direkt mit dem ESP zu machen und lässt den Arduino weg.

      Antworten
      1. Kabumdada

        Hallo Stefan,
        vielen Dank mal wieder für deine Antwort. Das klingt leider alles etwas kompliziert. Wir haben uns überlegt das ganze jetzt mittels UDP zu versuchen.
        Leider haben wir dabei Probleme mit dem senden bzw. empfangen und auswerten von strings. Das Beispielprog. Hilft da leider auch nicht arg viel weiter, da ich noch nicht so viel mit arduino Programmierung zu tun hatte. Hättest du da eventuell Tipps zu oder auch Anregungen wie man z.b. In der einen Routine blau schreibt und auf dem anderen den String auswärtet und falls der String blau ist die blaue led angeht?
        Vielen Dank.
        Gruß Marcel

        Antworten
  3. Norman Koplansky

    Hallo Stefan,
    hast du schon mal versucht mit der WiFi-Bridge (T2S) den Bootloader eines AVR – Arduinos anzusprechen ?
    Beim Yun gibt es die Möglichkeit. So kann man einen AVR über WiFi flashen. Wäre sehr praktisch für Updates in Projekte die aus AVR und ESP bestehen und irgendwo fest eingebaut sind. z.B. MarkiesenSteuerung o.ä.

    Norman

    Antworten
    1. ST Beitragsautor

      Hallo Norman,

      das müßte prinzipiell gehen. Es muss halt noch eine Logik dazu, um den Arduino zu resetten (das was bei dem normalen Adapter per DTR läuft). Bisher habe ich die Arduinos immer gesockelt und kann sie damit zum Neuflashen zur Not rausnehmen.

      Gruss Stefan

      Antworten
  4. Ulrich Piechnick

    Hallo Stefan,
    ich bin neu in dem ESP-Geschäft und von dem Beispielcode WiFiTelNetToSerial auf deinen Code gestoßen. Beide ähneln sich etwas daher frage ich dich mal um Rat.
    Das Beispiel funktioniert und dein Code sicher auch. Den Beispielcode betreibe ich mit dem ESP8266-01 und füttere die serielle Schnittstelle über einen LevelShifter mit 115200 Baud aus einem ATMega2560 (crumb2560). Die Richtung TelNet->uart brauche ich nicht. Die Daten sind das Logbuch aus einer SmartHome-Anwendung. Für die Empfängerseite nutze ich eine virtuelle Schnittstelle mit OCConsole oder auch Putty. Nun zu meinen Fragen:
    Bei mir fehlen gelegentlich Zeichen aus dem Log in dem Telnet-Datenstrom.
    Ich möchte den Server gern mit einem anderen Port betreiben, z. B. 5000, also nicht telnet.

    Kannst du mir zu den beiden Fragen etwas sagen?
    Vielen Dank.

    Antworten
    1. ST Beitragsautor

      Hallo Ulrich,

      bei dem Zugriff auf die Serielle wird keine Flusskontrolle verwendet. Also muss der ESP halt schnell genug sein, damit die Puffer nicht überlaufen und nichts verloren geht. Ich tippe mal auf diese Ursache. Ich habe die Brücke bisher bei 9600 Baud verwendet und das ist problemlos. Ob der eine oder andere Code besser ist, kann ich Dir nicht sagen. Einfach ausprobieren. Kannst Du die Brücke mit einer geringeren Baud Rate testen? – Alternativ bitte mal in der Arduino IDE unter Werkzeuge die CPU Frequenz auf 160MHz setzen. Ein schlechter WIFI Empfang kann das Problem auch verursachen. Oder irgendwelche String Befehle optimieren.
      Zum Port: Such im Code mal nach der folgenden Zeile: WiFiServer server(23);
      In Klammern kommt Dein Wunschport.

      Gruss Stefan

      Antworten
      1. Uli

        Hallo Stefan,
        danke für deine Infos. Das mit der PortNummer des Servers war ein Versehen. Ich hatte das vor dem Post versucht, und es hat nicht geklappt. Nach deinem Hinweis habe ich es noch einmal versucht. Diesmal mit Erfolg. Vermutlich habe ich mich am Anmelden des Cliets vertippt.

        Durch das Stichwort Flusskontrolle habe ich zum Thema RXBuffer gegoogled. Die Vergrößerung scheint in der aktuellen Version nicht mehr zu funktionieren. Ich habe deshalb den Timeout auf 1 mSek gesetzt und beim Senden der seriellen Daten am Ende des Textes eine kleine Pause eingelegt. Diese Kombination bracht den Erfolg. Es gehen keine Zeichen mehr verloren.

        Die Verringerung der Baudrate ist in meiner Microprozessoranwendung keine Option. Kostet zu viel Zeit.

        Mich würde noch eine Funktion interssieren, bei der die empfangenen Daten per Interrupt in einen Ringbuffer geschrieben werden. Kennst du da ein Beispiel?

        Vielen Dank für deine Unterstützung.

        Antworten
  5. Erik

    Hallo,
    ich würde gern eine normale Uart-Verbindung zwischen zwei ATmegas gegen eine Lösung mit zwei ESP8266-Modulen ersetzen. Ich bin im Moment auch noch auf der Suche nach geeigneten Möglichkeiten. Daher meine generelle Frage ist das mit deinem Code und den ESP8266-Modulen denkbar?
    Gruß

    Antworten
    1. ST Beitragsautor

      Hallo Erik, die Frage ist so etwas generisch gestellt. Du kannst zwei Mega so verbinden. Du musst natürlich den Code eines Esp8266 ändern. Sonst warten beide darauf, dass sich jemand einloggt.

      Gruss Stefan

      Antworten
      1. Erik

        Hallo,
        erstmal entschuldige für die vorhergehende unspezifische Frage… und danke für deinen Code. Der funktioniert prinzipiell auch. Ich kann einen AP erstellen und mit dem Handy als Client auch Daten austauschen. Will ich jedoch ein zweites Esp8266 als Client an den AP anmelden so funktioniert das leider nicht… Liegt das eventuell daran das beide Module die gleiche IP bekommen…?
        Gruß
        Erik

        Antworten
        1. Erik

          sorry… also an den IPs liegt es nicht. Der Client ESP8266 verbindet sich scheinbar korrekt mit dem AP ESP8266. Nutze ich das Handy zusätzlich kann ich an den Client 192.168.4.2 und an den AP 192.168.4.1 Daten senden. Aber wie bekommt man es hin das beide 192.168.4.1 AP und 192.168.4.2 Client Daten zueinander versenden?

          Antworten
          1. ST Beitragsautor

            Hi Erik,
            Der Code ist als Brücke zwischen Telnet und Serial aufgesetzt. Mehrere Clients können sind verbinden und mit der seriellen Schnittstelle sprechen. Was von der Schnittstelle kommt, geht zurück an alle Clients.
            Was Du möchtest ist eine Kommunikation zwischen den Clients. Das ist mit dem Konzept so nicht ganz kompatibel. Du kannst das natürlich im Code anpassen. Dann musst Du das was von einem Client kommt nicht nur an die serielle Schnittstelle verteilen, sondern auch an die anderen Clients. Den Code dazu hast Du im Prinzip auch vorliegen: das was von der seriellen Schnittstelle eingelesen wird, verteilt der Code ja auf alle Clients.

            Gruss Stefan

          2. Erik

            Hallo,
            und danke für deine Hilfe. Ich hab es jetzt (glaube ich ;-)) Bin Newbie was Arduino und Co. angeht. Im Prinzip brauche ich eine Verbindung zwischen einem Server und mehreren Clients. Die Clients sollen untereinander keine Daten austauschen können. Daher verwende ich deinen Code zum erzeugen des AP mit Server komplett. Somit müssen sich alle Clients (WIFI_STA) am AP/Server anmelden. Nur den Client Teil musste ich modifizieren. Es wird also eine 1 zu n Verbindung hergestellt.
            1 = Server = Accesspoint der Daten seiner Uart RX per Broadcast an alle Clients schick und Daten die er von den Clients erhält an die Uart TX weiterleitet
            n = Clients die sich an einem AP anmelden, Daten vom Server erhalten und an ihre Uart TX oder Daten der Uart RX an den Server weiterleiten
            Nochmal besten Dank. Gruß Erik

  6. Mäxx

    Hi Stefan,

    bin durch Zufall auf deinen Blog gestoßen, weil ich mich zum Thema ESP8266 eben erst einlese ( NodeMCUs sind gerade am Weg aus dem fernen China). Ich finde es super, dass du hier so viele Anwendungsbeispiele auf Ardionobasis vorstellt, dass macht glaube ich nicht nur mir den Einstieg in die ESP-Module leichter. Danke dir!

    Natürlich habe ich auch eine Frage an dich 😉
    Könnte mir die Frage wohl auch selbst beantworten, indem ichs einfach ausprobiere, aber die Module sind wie gesagt noch am Weg und ich kanns kaum erwarten….

    Ich habe eine Anwendung, in der ein Arduino einen Datenstring an mehrere Arduinos verteilt (nur unidirektional). Gehe ich richtig in der Annahme, dass ich mit deinem Code T2S genau das richtige gefunden hab und ohne Änderungen verwenden kann?

    Arduino String ->seriell zu ESP als AP (mit deiner Software) -> WiFi ——Luft;-)—–>WiFi->ESP als Client(mit deiner Software)->String zum Ardoino zur Weiterverarbeitung

    Empangen könnten dann alle Clients (max. 5) den selben gesendeten String den der AP sendet?

    Danke dir für deine Mühen,
    Grüße Mäxx

    Antworten
    1. ST Beitragsautor

      Hallo Mäxx,

      der Code ist dafür gemacht, dass er eine serielle Schnittstelle auf Telnet umsetzt. D.h. jemand muss auf Port 23 eine Verbindung zum ESP aufbauen und dort etwas senden bzw empfangen. Wenn Du einen ESP als AP nimmst und die anderen als WiFi-Clients , baut keiner beim anderen eine Verbindung auf. Es passiert gar nichts. Alle ESPs warten auf eine Verbindung.
      Was Du haben willst ist eine Brücke von seriell zu seriell über WiFi. Nicht exakt das selbe, aber ähnlich. Nimm z.B. einen ESP als AP, den anderen als Client. Dann baue eine Verbindung auf (WiFiClient). Dann kannst Du Daten hin und her senden.

      Gruss Stefan

      Antworten
      1. Mäxx

        Hi Stefan,

        danke dir für deine Rückmeldung. Werde wohl mal auf die Module warten. Wenn ich dann deine super dokumentierten Beispiele durchackern kann, wird sich einiges selbst erklären denke ich.

        Gruss Mäxx

        Antworten
  7. Hendrik

    Hallo,

    ich bin durch Zufall auf Ihren sehr interessanten Blog gestoßen. Dieser Artikel ist fantastisch, da man so einfach eine serielle Schnittstelle per Netzerk/Telnet anfunken kann! Wirklich super!

    Jetzt habe ich mir mal aus China ein paar Ethernet Shields mit dem W5500-Chip zugelegt und versucht das ganze auf Ethernet umzubauen. Klappt auch fast. Bis auf die Tatsache, dass die „EthernetServer“-Klasse keine Funktion „hasClient“ besitzt. Ich habe mal kurz in die Klassen reingeschaut, um herauszufinden, ob ich das nicht „Einfach“ aus der WifiServer-Klasse übernehmen kann… aber das bekomme ich nicht hin.

    Das Fehlerbild besteht lediglich darin, dass jedes mal wenn Daten am Ethernet-Port ankommen, ein neuer Socket aufgemacht wird. Die gesamte Socket-Verwaltung funktioniert irgendwie nicht.

    Können Sie vielleicht unterstützen?

    Hier mal mein geringfügig abgeänderter Code:

    #include
    #include

    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 60, 145);
    #define MAX_NO_CLIENTS 7
    const int iSerialSpeed = 9600;
    const bool bSuppressLocalEcho = false;

    EthernetServer server(23);
    EthernetClient pClientList[MAX_NO_CLIENTS];

    void setup() {
    pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
    digitalWrite(LED_BUILTIN, 1);

    // start serial
    Serial.begin(iSerialSpeed);

    Ethernet.begin(mac, ip);
    server.begin();
    Serial.print(„server is at „);
    Serial.println(Ethernet.localIP());
    }

    void loop() {

    int ii;

    if (server.available())
    {
    bool bFoundPlace = false;

    // search a free spot
    for (ii = 0; ii sorry
    if (!bFoundPlace)
    {
    EthernetClient client = server.available();
    client.stop();
    }

    /////////////////////
    // Telnet –> Serial
    /////////////////////
    for (ii = 0; ii Telnet
    /////////////////////
    if (Serial.available())
    {
    size_t len = Serial.available();
    uint8_t sbuf[len];
    Serial.readBytes(sbuf, len);

    for (ii = 0; ii < MAX_NO_CLIENTS; ii++)
    {
    if (pClientList[ii] && pClientList[ii].connected())
    {
    pClientList[ii].write(sbuf, len);
    delay(1);
    }
    }
    }

    }

    }

    Antworten
    1. ST Beitragsautor

      Hallo Hendrik,
      Ich habe mit den Ethernet Boards noch nie gearbeitet. Also kommt jetzt Theorie:
      Wenn ich in die Header Dateien schaue, dann gibt die server.availble Methode keinen Boolean zurück, sondern eine Client Instanz sofern vorhanden. Damit geht Dein Check if (server.available()) schief. Der schlägt an egal ob ein neuer oder bekannter Client verbunden wurde. In der Folge musst Du prüfen, ob Du diese Instanz schon kennst oder ob sie neu ist. Der Code ist auch in der WiFi Variante vorhanden; die Client Instanzen werden dort in dem Array verwaltet. Wenn Du also prüfst, ob Du den Client schon kennst und Dir die gültigen Instanzen im Array merkst, sollte es gehen.
      Gruss Stefan

      Antworten
      1. Hendrik

        Hallo Stefan,

        genau, dass hatte ich versucht zu formulieren ^^ Das ist das Problem. Und in der WiFi.Server-Class gibt es die Funktion/Eigenschaft „HasClient“ (Welche du ja auch verwendest) die meines Erachtens nach genau diesen Abgleich durchführt. Ob es halt ein neuer Client oder ein bekannter ist.

        Ich kann die Funktion nur nicht nachbilden, da ich nicht weiß, wo ich zum Vergleichen ansetzen muss bzw. wie ich die Instanz mit denen aus dem Array vergleichen kann.

        Ich versuche es nochmal weiter. Trotzdem vielen Dank! 🙂

        Gruß,
        Hendrik

        Antworten
        1. ST Beitragsautor

          Hallo Hendrik,

          in der pClientList merkst Du Dir die bekannten Clients. Setze diese Pointer im Setup alle auf NULL. Dann vergleiche bei einem Client, der Dir per .available() gemeldet wird, ob Du diesen schon kennst. Wenn nein, dann ist er wohl neu. Grob so würde ich es probieren.

          Gruss Stefan

          Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert