Hallo, ich bin soweit GCode Daten vom ESP32 zu meinem Arduino der mit GRBL 0.9 läuft zu Streamen. Hier soweit meine verkabelung von der Serial Kommunikation:
Ich habe mir die GRBL Docs angeschaut und die stream.py gefunden was ein beispiel zeigt Daten zu GRBL zu streamen darauf hin hatte ich versucht das in C nach zu machen hier mein Sketch:
#include <WiFi.h>
#include <LITTLEFS.h>
#include <ESPAsyncWebServer.h>
#include <WebSocketsServer.h>
#include <queue>
#include <vector>
#define FORMAT_LITTLEFS_IF_FAILED false
#define RXD2 16
#define TXD2 17
// Constants
const char *ssid = "Admin";
const char *password = "123456789";
const int http_port = 80;
const int led_pin = 2;
// Globals
AsyncWebServer server(http_port);
WebSocketsServer webSocket = WebSocketsServer(81);
// Gcode Queue
std::queue<char *> gcodeQueue;
bool waitingForOk = false;
/***********************************************************
Functions
*/
// Callback: receiving any WebSocket message
void onWebSocketEvent(uint8_t client_num,
WStype_t type,
uint8_t *payload,
size_t length)
{
// Figure out the type of WebSocket event
switch (type)
{
// Client has disconnected
case WStype_DISCONNECTED:
Serial.printf("[%u] Disconnected!\n", client_num);
break;
// New client has connected
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(client_num);
Serial.printf("[%u] Connection from ", client_num);
Serial.println(ip.toString());
}
break;
// For everything else: do nothing
case WStype_TEXT:
case WStype_BIN:
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
default:
break;
}
}
// Callback: send 404 if requested file does not exist
void onPageNotFound(AsyncWebServerRequest *request)
{
IPAddress remote_ip = request->client()->remoteIP();
Serial.println("[" + remote_ip.toString() +
"] HTTP GET request of " + request->url());
request->send(404, "text/plain", "Not found");
}
/***********************************************************
Main
*/
void setup()
{
// Start Serial port
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
// Make sure we can read the file system
if (!LITTLEFS.begin(FORMAT_LITTLEFS_IF_FAILED))
{
Serial.println("Error mounting SPIFFS");
return;
}
int tBytes = LITTLEFS.totalBytes();
int uBytes = LITTLEFS.usedBytes();
Serial.println("File system info");
Serial.print("Total bytes: ");
Serial.println(tBytes);
Serial.print("Used bytes: ");
Serial.println(uBytes);
// Start access point
WiFi.softAP(ssid, password);
// Print our IP address
Serial.println();
Serial.println("AP running");
Serial.print("My IP address: ");
Serial.println(WiFi.softAPIP());
server.serveStatic("/", LITTLEFS, "/");
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{
AsyncWebServerResponse* response = request->beginResponse(LITTLEFS, "/index.html", "text/html");
response->addHeader("Content-Encoding", "gzip");
request->send(response); });
server.on(
"/upload", HTTP_POST, [](AsyncWebServerRequest *request)
{ request->send(200); },
handleUpload);
server.on(
"/gcode", HTTP_POST, [](AsyncWebServerRequest *request)
{ request->send(200); },
handleGcode);
// Handle file delete
server.on("/delete", HTTP_DELETE, [](AsyncWebServerRequest *request)
{
if (request->hasParam("filename")) { // if the request has a parameter named "filename"
String filename = request->getParam("filename")->value(); // get the value of the "filename" parameter
if (LITTLEFS.remove("/" + filename)) { // attempt to delete the file
request->send(200, "text/plain", "Successfull deleted file: " + filename); // if successful, send a 200 OK response
} else {
request->send(500, "text/plain", "Failed to delete file"); // if unsuccessful, send a 500 Internal Server Error response
}
} else {
request->send(400, "text/plain", "Bad request"); // if the request does not have a "filename" parameter, send a 400 Bad Request response
} });
// Handle GET request for file list
server.on("/files", HTTP_GET, [](AsyncWebServerRequest *request)
{
if (request->hasParam("directory")) {
String directory = request->getParam("directory")->value();
String fileList = "";
File root = LITTLEFS.open(directory);
if (root && root.isDirectory()) {
File file = root.openNextFile();
while (file) {
String fileNameWithPath = file.name();
String fileName = fileNameWithPath.substring(directory.length());
fileList += fileName;
fileList += "\n";
file = root.openNextFile();
}
}
Serial.println(fileList);
request->send(200, "text/plain", fileList);
} else {
request->send(400, "text/plain", "Bad request");
} });
// Handle bytes check
server.on("/space", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(200, "text/plain", String(LITTLEFS.totalBytes()) + "," + String(LITTLEFS.usedBytes())); });
// Handle requests for pages that do not exist
server.onNotFound(onPageNotFound);
// Start web server
server.begin();
// Start WebSocket server and assign callback
webSocket.begin();
// enable heartbeat for websocket
webSocket.enableHeartbeat(15000, 3000, 2);
webSocket.onEvent(onWebSocketEvent);
}
#define RX_BUFFER_SIZE 128 // adjust this to your needs
#define MAX_GCODE_LENGTH 128 // adjust this to your needs
int g_count = 0;
int l_count = 0;
int error_count = 0;
bool verbose = true;
int len = 0;
char l_block[MAX_GCODE_LENGTH];
void loop()
{
webSocket.loop();
if (!gcodeQueue.empty())
{
bool okReceived = false;
char *l_block = gcodeQueue.front();
gcodeQueue.pop();
len = strlen(l_block) + 1;
while (len >= RX_BUFFER_SIZE - 1 || Serial2.available())
{
char out_temp[RX_BUFFER_SIZE];
Serial2.readBytesUntil('\n', out_temp, RX_BUFFER_SIZE);
if (strstr(out_temp, "ok") == NULL && strstr(out_temp, "error") == NULL)
{
Serial.println(" MSG: \"" + String(out_temp) + "\""); // Debug response
}
else
{
if (!okReceived && strstr(out_temp, "ok") != NULL)
{
okReceived = true;
g_count += 1;
len -= strlen(l_block) + 1;
if (verbose)
Serial.println(" REC<" + String(g_count) + ": \"" + String(out_temp) + "\"");
}
if (strstr(out_temp, "error") != NULL)
error_count += 1;
}
}
Serial2.println(l_block); // Send g-code block to grbl
if (verbose)
Serial.println("SND>" + String(l_count) + ": \"" + String(l_block) + "\"");
l_count += 1;
delete[] l_block; // delete the gcode line when done with it
}
// Wait until all responses have been received.
while (l_count > g_count)
{
bool okReceived = false;
char out_temp[RX_BUFFER_SIZE];
Serial2.readBytesUntil('\n', out_temp, RX_BUFFER_SIZE);
if (strstr(out_temp, "ok") == NULL && strstr(out_temp, "error") == NULL)
{
Serial.println(" MSG: \"" + String(out_temp) + "\""); // Debug response
}
else
{
if (!okReceived && strstr(out_temp, "ok") != NULL)
{
okReceived = true;
g_count += 1;
len -= strlen(l_block) + 1;
if (verbose)
Serial.println(" REC<" + String(g_count) + ": \"" + String(out_temp) + "\"");
}
if (strstr(out_temp, "error") != NULL)
error_count += 1;
}
}
}
void ReceivedGCodeData(uint8_t *payload, size_t length)
{
// Tokenize the payload into lines
char *token;
char *saveptr;
token = strtok_r((char *)payload, ",", &saveptr);
while (token != NULL)
{
byte mode = 0;
if (strcmp(token, "M7") == 0)
{
mode = 1;
}
if (strcmp(token, "M8") == 0)
{
mode = 1;
}
if (strcmp(token, "M2") == 0)
{
mode = 1;
}
if (strncmp(token, "G1", 2) == 0)
{
mode = 1;
}
if (strncmp(token, "G0", 2) == 0)
{
mode = 1;
}
if (strcmp(token, "G21") == 0)
{
mode = 1;
}
if (strcmp(token, "G90") == 0)
{
mode = 1;
}
if (strncmp(token, "G92", 3) == 0)
{
mode = 1;
}
if (strcmp(token, "F1250") == 0)
{
mode = 1;
}
if (mode == 1)
{
char *gcodeLine = new char[strlen(token) + 1];
strcpy(gcodeLine, token);
gcodeQueue.push(gcodeLine);
}
token = strtok_r(NULL, ",", &saveptr);
}
// Flush the Serial2 buffer
Serial2.flush();
}
// handles uploads
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final)
{
String logmessage = "Client:" + request->client()->remoteIP().toString() + " " + request->url();
Serial.println(logmessage);
if (!index)
{
logmessage = "Upload Start: " + String(filename);
// open the file on first call and store the file handle in the request object
request->_tempFile = LITTLEFS.open("/" + filename, "w");
Serial.println(logmessage);
}
if (len)
{
// stream the incoming chunk to the opened file
request->_tempFile.write(data, len);
logmessage = "Writing file: " + String(filename) + " index=" + String(index) + " len=" + String(len);
Serial.println(logmessage);
}
if (final)
{
logmessage = "Upload Complete: " + String(filename) + ",size: " + String(index + len);
// close the file handle as the upload is now done
request->_tempFile.close();
Serial.println(logmessage);
}
}
// handles gcode file uploads
void handleGcode(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final)
{
static std::vector<uint8_t> buffer;
if (!index)
{
Serial.println("Gcode received");
// Wake up Grbl in the time between uploads
Serial2.println("\r\n\r\n");
// Clear the buffer
buffer.clear();
}
if (len)
{
// Append the incoming data to the buffer
buffer.insert(buffer.end(), data, data + len);
}
if (final)
{
Serial.println("Gcode upload complete");
// Send the buffer to ReceivedGCodeData
ReceivedGCodeData(buffer.data(), buffer.size());
// Clear the buffer
buffer.clear();
}
}
Die Daten also handleGcode kommt vom Client (Auf dem ESP32 läuft ein Webserver) aber das scheint alles normal zu funktionieren, jetzt das Problem: Das Sketch so funktioniert bedeutet ich lade den Gcode hoch und er wird auch sehr effizient abgefahren, jedoch bei manchen GCodes gehen Daten am ende verloren also so sieht ein Beispiel von Daten aus:
G21
G90
F1250
M8
G92 X0 Y0
G0 X19.58 Y7.75
M7
G1 X19.48 Y7.75
G1 X17.27 Y7.75
G1 X15.58 Y8.18
G1 X14.10 Y9.23
G1 X12.84 Y10.71
G1 X11.68 Y12.18
G1 X10.84 Y13.66
G1 X10.10 Y15.03
G1 X9.47 Y16.82
G1 X9.25 Y18.93
G1 X9.36 Y21.46
G1 X10.10 Y22.93
G1 X11.05 Y24.20
G1 X12.21 Y25.46
G1 X13.47 Y26.41
G1 X15.26 Y27.15
G1 X17.27 Y27.68
G1 X19.27 Y27.89
G1 X21.48 Y27.89
G1 X23.80 Y27.68
G1 X25.80 Y27.36
G1 X27.49 Y26.62
G1 X28.75 Y25.67
G1 X29.70 Y24.51
G1 X30.55 Y23.04
G1 X31.07 Y21.25
G1 X31.39 Y19.56
G1 X31.39 Y17.35
G1 X31.18 Y15.34
G1 X30.34 Y13.66
G1 X29.39 Y12.29
G1 X28.02 Y11.13
G1 X26.54 Y10.39
G1 X24.85 Y9.65
G1 X23.17 Y9.12
G1 X21.48 Y8.49
G1 X19.90 Y7.86
M8
M2
G0 X0 Y0
GCODE
Das GCODE am ende hat keinen wirklichen einfluss außer das es das "G0 X0 Y0" noch in die gcodeQueue macht aber ist ja egal die Daten kommen aufjedenfall an also ich bekomme für jede Zeile ein SND Debug Response, aber wie gesagt bei manchen GCode Kombinationen kommt zum beispiel das "M8" am ende nicht durch oder auch "G0 X0 Y0" ich weiß nicht woran es liegt, vielleicht der Code sendet zu schnell, der Code kriegt das Ok für ein ganz anderen GCode vorher kein plan, so sieht das erste Protokol während des verarbeiten aus (Also vom GCode den ich da oben reingepackt habe):
Gcode received
Gcode upload complete
REC<1: "ok"
SND>0: "G21"
SND>1: "G90"
REC<2: "ok"
REC<3: "ok"
SND>2: "F1250"
REC<4: "ok"
SND>3: "M8"
SND>4: "G92 X0 Y0"
REC<5: "ok"
REC<6: "ok"
SND>5: "G0 X19.58 Y7.75"
SND>6: "M7"
REC<7: "ok"
REC<8: "ok"
SND>7: "G1 X19.48 Y7.75"
REC<9: "ok"
SND>8: "G1 X17.27 Y7.75"
REC<10: "ok"
SND>9: "G1 X15.58 Y8.18"
SND>10: "G1 X14.10 Y9.23"
MSG: ""
REC<11: "ok"
REC<12: "ok"
SND>11: "G1 X12.84 Y10.71"
REC<13: "ok"
SND>12: "G1 X11.68 Y12.18"
SND>13: "G1 X10.84 Y13.66"
REC<14: "ok"
REC<15: "ok"
SND>14: "G1 X10.10 Y15.03"
REC<16: "ok"
SND>15: "G1 X9.47 Y16.82"
REC<17: "ok"
SND>16: "G1 X9.25 Y18.93"
SND>17: "G1 X9.36 Y21.46"
REC<18: "ok"
REC<19: "ok"
SND>18: "G1 X10.10 Y22.93"
SND>19: "G1 X11.05 Y24.20"
REC<20: "ok"
REC<21: "ok"
SND>20: "G1 X12.21 Y25.46"
SND>21: "G1 X13.47 Y26.41"
REC<22: "ok"
REC<23: "ok"
SND>22: "G1 X15.26 Y27.15"
SND>23: "G1 X17.27 Y27.68"
REC<24: "ok"
REC<25: "ok"
SND>24: "G1 X19.27 Y27.89"
SND>25: "G1 X21.48 Y27.89"
REC<26: "ok"
REC<27: "ok"
SND>26: "G1 X23.80 Y27.68"
SND>27: "G1 X25.80 Y27.36"
REC<28: "ok"
REC<29: "ok"
SND>28: "G1 X27.49 Y26.62"
SND>29: "G1 X28.75 Y25.67"
REC<30: "ok"
REC<31: "ok"
SND>30: "G1 X29.70 Y24.51"
SND>31: "G1 X30.55 Y23.04"
REC<32: "ok"
REC<33: "ok"
SND>32: "G1 X31.07 Y21.25"
SND>33: "G1 X31.39 Y19.56"
REC<34: "ok"
REC<35: "ok"
SND>34: "G1 X31.39 Y17.35"
SND>35: "G1 X31.18 Y15.34"
REC<36: "ok"
REC<37: "ok"
SND>36: "G1 X30.34 Y13.66"
SND>37: "G1 X29.39 Y12.29"
REC<38: "ok"
REC<39: "ok"
SND>38: "G1 X28.02 Y11.13"
SND>39: "G1 X26.54 Y10.39"
REC<40: "ok"
REC<41: "ok"
SND>40: "G1 X24.85 Y9.65"
SND>41: "G1 X23.17 Y9.12"
REC<42: "ok"
REC<43: "ok"
SND>42: "G1 X21.48 Y8.49"
SND>43: "G1 X19.90 Y7.86"
REC<44: "ok"
REC<45: "ok"
SND>44: "M8"
SND>45: "M2"
REC<46: "ok"
REC<47: "ok"
SND>46: "G0 X0 Y0"
Beim Zweiten mal senden vom exakt selbem Gcode sieht das schon wieder anders (Das Protokol):
Gcode received
Gcode upload complete
REC<48: "ok"
MSG: "[Pgm End] number format�n2>�n2/"
SND>47: "G21"
SND>48: "G90"
REC<49: "ok"
REC<50: "ok"
SND>49: "F1250"
REC<51: "ok"
SND>50: "M8"
REC<52: "ok"
SND>51: "G92 X0 Y0"
SND>52: "G0 X19.58 Y7.75"
REC<53: "ok"
REC<54: "ok"
SND>53: "M7"
REC<55: "ok"
SND>54: "G1 X19.48 Y7.75"
REC<56: "ok"
SND>55: "G1 X17.27 Y7.75"
SND>56: "G1 X15.58 Y8.18"
MSG: ""
REC<57: "ok"
REC<58: "ok"
SND>57: "G1 X14.10 Y9.23"
REC<59: "ok"
SND>58: "G1 X12.84 Y10.71"
SND>59: "G1 X11.68 Y12.18"
REC<60: "ok"
REC<61: "ok"
SND>60: "G1 X10.84 Y13.66"
REC<62: "ok"
SND>61: "G1 X10.10 Y15.03"
REC<63: "ok"
SND>62: "G1 X9.47 Y16.82"
REC<64: "ok"
SND>63: "G1 X9.25 Y18.93"
SND>64: "G1 X9.36 Y21.46"
REC<65: "ok"
REC<66: "ok"
SND>65: "G1 X10.10 Y22.93"
SND>66: "G1 X11.05 Y24.20"
REC<67: "ok"
REC<68: "ok"
SND>67: "G1 X12.21 Y25.46"
SND>68: "G1 X13.47 Y26.41"
REC<69: "ok"
REC<70: "ok"
SND>69: "G1 X15.26 Y27.15"
SND>70: "G1 X17.27 Y27.68"
REC<71: "ok"
REC<72: "ok"
SND>71: "G1 X19.27 Y27.89"
SND>72: "G1 X21.48 Y27.89"
REC<73: "ok"
REC<74: "ok"
SND>73: "G1 X23.80 Y27.68"
SND>74: "G1 X25.80 Y27.36"
REC<75: "ok"
REC<76: "ok"
SND>75: "G1 X27.49 Y26.62"
SND>76: "G1 X28.75 Y25.67"
REC<77: "ok"
REC<78: "ok"
SND>77: "G1 X29.70 Y24.51"
SND>78: "G1 X30.55 Y23.04"
REC<79: "ok"
REC<80: "ok"
SND>79: "G1 X31.07 Y21.25"
SND>80: "G1 X31.39 Y19.56"
REC<81: "ok"
REC<82: "ok"
SND>81: "G1 X31.39 Y17.35"
SND>82: "G1 X31.18 Y15.34"
REC<83: "ok"
REC<84: "ok"
SND>83: "G1 X30.34 Y13.66"
SND>84: "G1 X29.39 Y12.29"
REC<85: "ok"
REC<86: "ok"
SND>85: "G1 X28.02 Y11.13"
SND>86: "G1 X26.54 Y10.39"
REC<87: "ok"
REC<88: "ok"
SND>87: "G1 X24.85 Y9.65"
SND>88: "G1 X23.17 Y9.12"
REC<89: "ok"
REC<90: "ok"
SND>89: "G1 X21.48 Y8.49"
SND>90: "G1 X19.90 Y7.86"
REC<91: "ok"
REC<92: "ok"
SND>91: "M8"
SND>92: "M2"
REC<93: "ok"
REC<94: "ok"
SND>93: "G0 X0 Y0"
Die beiden Protokols sind aus dem exakt selbem GCode der eine war das erste mal der andere das zweite mal (Beide hatten das "M8" am ende verloren) warum auch immer, kein plan vielleicht hat ja jemand eine idee, Danke schonmal
