Currently, I am building a system composed of a Arduino WebSockets server (running on ATmega328P with a W5500 Ethernet Shield), which sends a value to a python client when it is queried every 2 seconds. It then takes the obtained value with the corresponding timestamp and writes it to a .csv file. I have recently upgraded to python 3.9.6 in order to use asyncio.run()
in the python client too. The Arduino WebSockets server is given below:
#include <WebSocketServer.h>
using namespace net;
//------------------------------------------------------
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[]{0xA8, 0x61, 0x0A, 0xAE, 0x69, 0x13};
IPAddress ip(198, 162, 1, 177);
IPAddress gateway(0,0,0,0);
IPAddress DNSserver(0,0,0,0);
IPAddress subnet(255,255,255,0);
constexpr uint16_t port = 80;
WebSocketServer wss{port};
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
pinMode(Pulses, INPUT);
attachInterrupt(digitalPinToInterrupt(Pulses), CountPulses, FALLING);
Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac,ip,DNSserver,gateway,subnet);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
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;
}
ws.send(dataType, message, length);
});
ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *,
uint16_t) {
Serial.println(F("Disconnected"));
});
Serial.print(F("New client: "));
Serial.println(ws.getRemoteIP());
char temperature[10];
char str_temp[8];
float temp = 1001.01;
/* 4 is mininum width, 2 is precision; float value is copied onto str_temp*/
dtostrf(temp, 6, 2, str_temp);
sprintf(temperature,"%s", str_temp);
float value;
value = 0.1;
const char message[] {value};
ws.send(WebSocket::DataType::TEXT, temperature, strlen(temperature));
});
wss.begin();
Serial.println(Ethernet.localIP());
}
void loop() {
wss.listen();
}
The asyncio python client is given below:
import logging
import datetime
logger = logging.getLogger("websockets")
logger.setLevel(
logging.DEBUG
) # Switch to DEBUG for full error information
logger.addHandler(logging.StreamHandler())
async def get_data():
async with websockets.connect(
"ws://198.162.1.177:80/",
ping_interval=None,
) as websocket:
await websocket.send(str(1.001))
response = await websocket.recv()
return response
def save_data(response):
now = datetime.datetime.now()
dataline_pv1 = f"{now.isoformat()},{response},0\n"
file_name_pv1 = f"{now:%Y%m%d}_flow.csv"
with open(file_name_pv1, "a") as etherm_file1:
etherm_file1.write(dataline_pv1)
async def test():
while True:
response = await get_data()
save_data(response)
await asyncio.sleep(1)
asyncio.run(test())
However, I am experiencing some very odd behavior with the connection (perhaps memory related, since I want to have the Arduino effectively operate continuously?). Sometimes, my laptop cannot connect to the Arduino,leading to a Connection Refused
error, despite being able to ping it from the terminal.
On other occasions, both the client and the server can run successfully, but then the connection appears to freeze and the .csv file appears to stop updating after about 3 minutes or so, without giving an error message in the terminal.
What is happening here, and how do I fix this such that Arduino can run continuously without this freezing occurring?