Vincent Dw
New member
Hi everyone,
I am building a showlaser for my graduation assignment. I use the teensy 4.1 as the controller in the laser and my pc to send commands to the teensy 4.1 by a websockets connection. I succeeded in setting up the communication, but there is one thing wrong. When i send like 5000 messages in a for loop the Teensy crashes and the connection is lost. If i send 50 messages to the teensy the teensy does not crash and the connection remains.
My goal is to send around 30000 messages per second, with a stable connection. The message is a string and looks like this "x:-4000", "r:255". Are websockets suited for this use case or are their better ways to accomplish this? I would really like to use the ethernet connection since i had problems with serial being too laggy for the laser in the previous showlaser version that i build.
Below is the code i used for the teensy.
The teensy code is the example sketch found in Websockets2_Generic -> Generic -> Teensy41_NativeEthernet -> MultipleClients_Teensy41_Server.
This is the c# code i use on the computer.
The sendMessage method
I am building a showlaser for my graduation assignment. I use the teensy 4.1 as the controller in the laser and my pc to send commands to the teensy 4.1 by a websockets connection. I succeeded in setting up the communication, but there is one thing wrong. When i send like 5000 messages in a for loop the Teensy crashes and the connection is lost. If i send 50 messages to the teensy the teensy does not crash and the connection remains.
My goal is to send around 30000 messages per second, with a stable connection. The message is a string and looks like this "x:-4000", "r:255". Are websockets suited for this use case or are their better ways to accomplish this? I would really like to use the ethernet connection since i had problems with serial being too laggy for the laser in the previous showlaser version that i build.
Below is the code i used for the teensy.
The teensy code is the example sketch found in Websockets2_Generic -> Generic -> Teensy41_NativeEthernet -> MultipleClients_Teensy41_Server.
Code:
/****************************************************************************************************************************
MultiClients_Teensy41_Server.ino
For Teensy 4.1 with NativeEthernet.
Based on and modified from Gil Maimon's ArduinoWebsockets library https://github.com/gilmaimon/ArduinoWebsockets
to support STM32F/L/H/G/WB/MP1, nRF52, SAMD21/SAMD51, SAM DUE, Teensy boards besides ESP8266 and ESP32
The library provides simple and easy interface for websockets (Client and Server).
Built by Khoi Hoang https://github.com/khoih-prog/Websockets2_Generic
Licensed under MIT license
*****************************************************************************************************************************/
/*
Teensy41 Websockets Server and Http Server (using NativeEthernet).
Combining the Teensy41-Server example with the NativeEthernet WebServer
example (https://github.com/vjmuzik/NativeEthernet/blob/master/examples/WebServer/WebServer.ino).
This sketch:
1. Connects to a ethernet network
2. Starts a websocket server on port 80
3. Waits for connections
4. As soon as a client wants to establish a connection, it checks whether a
free slot is available and accepts it accordingly
5. If the client is accepted it sends a welcome message and echoes any
messages from the client
6. Goes back to step 3
Note:
Make sure you share your computer's internet connection with the Teensy
via ethernet.
Libraries:
To use this sketch install
TeensyID library (https://github.com/sstaub/TeensyID)
NativeEthernet (https://github.com/vjmuzik/NativeEthernet)
Hardware:
For this sketch you need a Teensy 4.1 board and the Teensy 4.1 Ethernet Kit
(https://www.pjrc.com/store/ethernet_kit.html).
Written by https://github.com/arnoson
*/
#if !(defined(__IMXRT1062__) && defined(ARDUINO_TEENSY41))
#error This is designed only for Teensy 4.1. Please check your Tools-> Boards
#endif
#define WEBSOCKETS_USE_ETHERNET true
#define USE_NATIVE_ETHERNET true
#include <WebSockets2_Generic.h>
using namespace websockets2_generic;
// We will set the MAC address at the beginning of `setup()` using TeensyID's
// `teensyMac` helper.
byte mac[6];
// Enter websockets server port.
const uint16_t port = 81;
// Define how many clients we accpet simultaneously.
const byte maxClients = 4;
WebsocketsClient clients[maxClients];
WebsocketsServer server;
void teensyMAC(uint8_t *mac) {
for(uint8_t by=0; by<2; by++) mac[by]=(HW_OCOTP_MAC1 >> ((1-by)*8)) & 0xFF;
for(uint8_t by=0; by<4; by++) mac[by+2]=(HW_OCOTP_MAC0 >> ((3-by)*8)) & 0xFF;
Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
void setup()
{
// Set the MAC address.
teensyMAC(mac);
// Start Serial and wait until it is ready.
Serial.begin(115200);
while (!Serial);
Serial.println("\nStart MultiClients_Teensy41_Server on Teensy 4.1");
Serial.println(WEBSOCKETS2_GENERIC_VERSION);
// Connect to ethernet.
if (Ethernet.begin(mac))
{
Serial.println("Ethernet connected");
}
else
{
Serial.println("Ethernet failed");
}
// Start websockets server.
server.listen(port);
if (server.available())
{
Serial.print("Server available at ws://");
Serial.print(Ethernet.localIP());
// Also log any non default port.
if (port != 80)
Serial.printf(":%d", port);
Serial.println();
}
else
{
Serial.println("Server not available!");
}
}
void handleMessage(WebsocketsClient &client, WebsocketsMessage message)
{
auto data = message.data();
Serial.println("Data: " + data);
}
void handleEvent(WebsocketsClient &client, WebsocketsEvent event, String data)
{
if (event == WebsocketsEvent::ConnectionClosed)
{
Serial.println("Connection closed");
}
}
int8_t getFreeClientIndex()
{
// If a client in our list is not available, it's connection is closed and we
// can use it for a new client.
for (byte i = 0; i < maxClients; i++)
{
if (!clients[i].available())
return i;
}
return -1;
}
void listenForClients()
{
if (server.poll())
{
int8_t freeIndex = getFreeClientIndex();
if (freeIndex >= 0)
{
WebsocketsClient newClient = server.accept();
newClient.onMessage(handleMessage);
newClient.onEvent(handleEvent);
clients[freeIndex] = newClient;
}
}
}
void pollClients()
{
for (byte i = 0; i < maxClients; i++)
{
clients[i].poll();
}
}
void loop()
{
listenForClients();
pollClients();
}
This is the c# code i use on the computer.
Code:
for (int i = 0; i < 50; i++)
{
await _laserConnection.SendMessage($"x:{new Random(Guid.NewGuid().GetHashCode()).Next(-4000, 4000)}");
}
The sendMessage method
Code:
public async Task SendMessage(string message)
{
var rcvBytes = Encoding.ASCII.GetBytes(message);
var rcvBuffer = new ArraySegment<byte>(rcvBytes);
bool messageSend = false;
int connectionAttempts = 0;
while (!messageSend)
{
connectionAttempts++;
if (connectionAttempts > 1)
{
Console.WriteLine(connectionAttempts);
}
try
{
await _clientWebSocket.SendAsync(rcvBuffer, WebSocketMessageType.Binary, true, CancellationToken.None);
messageSend = true;
}
catch (Exception)
{
await Connect();
}
}
}