Uno R4 Wifi and WebSockets

I have a project where I want to use websockets to communicate between a web page running in a browser and a stepper motor controlled by the Arduino.

I can get a simple web page served up by the Arduino to work.

I can get the stepper motor controlled by the Arduino to work.

What I'm having trouble with is getting both a simple web server and web socket server running simultaneously on the Arduino.

To simplify things I tried running the code for a web chat application which serves up a page using static html from port 80 and then has a web socket listening on port 81.

This uses the ArduinoCore-renesas WiFiS3 web server running on port 80 to serve the web page. This page has some javascript embedded to interact with the page and send commands back to the Arduino over port 81, which is the websocket server, using the mWebSockets library.

I can get it compiled and uploaded to the R4 Uno Wifi, the Arduino gets a DHCP assigned IP address from my router and I can then use a browser on my desktop to load the web page.

From that web page I can Connect to the web socket server and see the connection succeed - both in the serial monitor and from the feedback on the web page.

However if I then type in a message such as "Hi from firefox" and click Send, the serial monitor shows

<< ⸮⸮;⸮q⸮s⸮Q⸮I⸮⸮}⸮⸮]⸮	⸮

Clicking Disconnect shows

<< ⸮⸮⸮5⸮b

From the formatting of those lines with the "<<" prefix it appears this is being handled by the web server running on port 80, not the websocket server running on port 81.

What should I be checking next ?

1 Like

Serial monitor baud rate? You didn't post the code, so check the Serial.begin() baud rate and ensure the baud on the serial monitor match.

Thanks, I've followed the code exactly as in the online tutorial. I get readable feedback in the serial monitor until the web socket stuff starts (and this is what fails to do what it says on the tin).

/*
 * Created by ArduinoGetStarted.com
 * This example code is in the public domain
 * Tutorial page: https://arduinogetstarted.com/tutorials/arduino-websocket
 */

#include <WiFiS3.h>
#include <WebSocketServer.h>
#include "index.h"

using namespace net;

WebSocketServer wss(81);
WiFiServer server(80);

const char ssid[] = "****";  // change your network SSID
const char pass[] = "****";   // change your network password

int status = WL_IDLE_STATUS;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);

  String fv = WiFi.firmwareVersion();
  // version is 0.2.1
  if (fv < WIFI_FIRMWARE_LATEST_VERSION)
    Serial.println("Please upgrade the firmware");

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 4 seconds for connection:
    delay(4000);
  }

  // print your board's IP address:
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  server.begin();

  wss.onConnection([](WebSocket &ws) {
    const auto protocol = ws.getProtocol();
    if (protocol) {
      Serial.print(F("Client protocol: "));
      Serial.println(protocol);
    }

    ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType,
                    const char *message, uint16_t length) {
      switch (dataType) {
        case WebSocket::DataType::TEXT:
          Serial.print(F("Received: "));
          Serial.println(message);
          break;
        case WebSocket::DataType::BINARY:
          Serial.println(F("Received binary data"));
          break;
      }

      String reply = "Received: " + String((char *)message);
      ws.send(dataType, reply.c_str(), reply.length());
    });

    ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *,
                  uint16_t) {
      Serial.println(F("Disconnected"));
    });

    Serial.print(F("New WebSocket Connnection from client: "));
    Serial.println(ws.getRemoteIP());

    const char message[]{ "Hello from Arduino server!" };
    ws.send(WebSocket::DataType::TEXT, message, strlen(message));
  });

  wss.begin();
}

void loop() {
  wss.listen();

  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    // read the HTTP request header line by line
    while (client.connected()) {
      if (client.available()) {
        String HTTP_header = client.readStringUntil('\n');  // read the header line of HTTP request

        if (HTTP_header.equals("\r"))  // the end of HTTP request
          break;

        Serial.print("<< ");
        Serial.println(HTTP_header);  // print HTTP request to Serial Monitor
      }
    }

    // send the HTTP response header
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Connection: close");  // the connection will be closed after completion of the response
    client.println();                     // the separator between HTTP header and body

    String html = String(HTML_CONTENT);

    client.println(html);
    client.flush();

    // give the web browser time to receive the data
    delay(50);

    // close the connection:
    client.stop();
  }
}

When you open the serial monitor, what does it say at the bottom right? Select Carriage return. Here are the choices in that drop down window:
No line ending
Newline
Carriage return
Both NL & CR

I too think it's a baud rate mismatch issue.

Thanks for your help. It is not the character encoding, or baud rate etc.
The serial monitor correctly displays the Serial.println commands from when the initial wifi connection is made, the web page served out to the browser etc.

The problem is that in the loop function, the web server on port 80 is receiving commands for the web socket server (port 81), you see this as the folowing two lines of logging code is putting the jibberish onto the monitor

        Serial.print("<< ");
        Serial.println(HTTP_header);  // print HTTP request to Serial Monitor

No, that has been ruled out - see reply #6

I need to use wire shark on the PC to see what the browser is sending over the wire.

Just to clarify, here is a copy of the Serial Monitor output. You can see the initial request on port 80 to output the web page to the browser is fine. It is the subsequent request on port 81 (the web socket port) that is getting processed by the code bound to port 80 (the last line)

IP Address: 192.168.0.194
<< GET / HTTP/1.1
<< Host: 192.168.0.194
<< User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0
<< Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
<< Accept-Language: en-GB,en;q=0.5
<< Accept-Encoding: gzip, deflate
<< Connection: keep-alive
<< Upgrade-Insecure-Requests: 1
<< Priority: u=1
New WebSocket Connnection from client: 192.168.0.237
<< ��e���h��

The second to last line is the initial establishment of the web socket connection

Fixed it !!!

Even though this is a board I only purchased last month, the ESP32 radio link firmware was way out of date. So it has been sitting on the shelf at Farnell / Element 14 I'm guessing.

The version reported by

WiFi.firmwareVersion();

was 0.2.1

The current version is 0.4.1
The process to upgrade was not straightforward, probably because the version was out of date and so not compatible with the IDE ?

I created a separate thread in the R4 Wifi category detailing what was required to get the upgrade working.

Anyway the correct behaviour is now observed so I can go back to the original problem: controlling my blinds via a stepper.

1 Like

Got my R4 Wifi a month ago and found the same version of firmware (0.2.1). Just updated to 0.4.1. Thanks for the post!

2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.