MKS WIFI for Makerbase Robin: firmware upgrade and new Web Socket features – 4
I bought a FlyingBear Ghost 5 with an integrated WiFi module, but I discovered no web interface. I don’t know why they can’t add a basic user interface. Then I went to see the web interface of the high-end Makerbase cards and realized that it was better they didn’t develop it.
My solution was to modify the firmware to support the Web Socket and develop the Web interface. This feature is compatible with all Makerbase cards with an MKS WiFi module.
The result of the BeePrint Web interface is in this screenshot.
I also decided to explain all the development phases of the project. In this article, I would like to expose the hardware infrastructure of the MKS WiFi card that interfaces with the Makerbase Robin Nano.
Now we will analyze the changes I made to the original MKS WiFi module, with the introduction of Web Socket and some minor features to develop Web interface and debug.
MKS WiFi upgrades
I made some changes to the original code, the old functions remain the same, but I must add a WebSocket server service and some endpoint for additional features.
But these changes use a bit of additional memory, so we lost the OTA update for Filesystem. When we need to upload the Filesystem again, we must downgrade the firmware, upload the Filesystem and upload the firmware again.
WebSocket code
The section that manages the message is this.
bool manageMessage(char* readStr, int readSize){
//transfer file
#if 0
if(strstr((const char *)readStr, "M29") != 0)
{
if(!verification_flag)
{
break;
}
if(transfer_state != TRANSFER_IDLE)
{
rcv_end_flag = true;
net_print((const uint8_t *) "ok\n", strlen((const char *)"ok\n"));
break;
}
}
#endif
DEBUG_PRINT(F("transfer_file_flag "));
DEBUG_PRINTLN(transfer_file_flag);
DEBUG_PRINT(F("verification_flag "));
DEBUG_PRINTLN(verification_flag);
DEBUG_PRINT(F("readStr "));
DEBUG_PRINTLN(readStr);
DEBUG_PRINT(F("readSize "));
DEBUG_PRINTLN(readSize);
if(transfer_file_flag)
{
if(!verification_flag)
{
return false;
}
if(gFileFifo.left() >= readSize)
{
gFileFifo.push((char *)readStr, readSize);
transfer_frags += readSize;
}
}
else
{
if(verification_flag)
{
int j = 0;
char cmd_line[100] = {0};
String gcodeM3 = "";
#if 0
if(transfer_state == TRANSFER_BEGIN)
{
if(strstr((const char *)readStr, "M110") != 0)
{
file_fragment = 0;
rcv_end_flag = false;
transfer_file_flag = true;
if(package_file_first(filePath) == 0)
{
/*transfer_state = TRANSFER_READY;
digitalWrite(EspReqTransferPin, LOW);*/
}
else
{
transfer_file_flag = false;
transfer_state = TRANSFER_IDLE;
}
net_print((const uint8_t *) "ok\n", strlen((const char *)"ok\n"));
break;
}
}
#endif
init_queue(&cmd_queue);
cmd_index = 0;
memset(cmd_fifo, 0, sizeof(cmd_fifo));
while(j < readSize)
{
if((readStr[j] == '\r') || (readStr[j] == '\n'))
{
if((cmd_index) > 1)
{
cmd_fifo[cmd_index] = '\n';
cmd_index++;
push_queue(&cmd_queue, cmd_fifo, cmd_index);
}
memset(cmd_fifo, 0, sizeof(cmd_fifo));
cmd_index = 0;
}
else if(readStr[j] == '\0')
break;
else
{
if(cmd_index >= sizeof(cmd_fifo))
{
memset(cmd_fifo, 0, sizeof(cmd_fifo));
cmd_index = 0;
}
cmd_fifo[cmd_index] = readStr[j];
cmd_index++;
}
j++;
do_transfer();
yield();
}
while(pop_queue(&cmd_queue, cmd_line, sizeof(cmd_line)) >= 0)
{
#if 0
point = strstr((const char *)cmd_line, "M28 ");
if(point != 0)
{
if((strstr((const char *)cmd_line, ".g") || strstr((const char *)cmd_line, ".G")))
{
int index = 0;
char *fileName;
point += 3;
while(*(point + index) == ' ')
index++;
memcpy((char *)filePath, (const char *)(point + index), readSize - (int)(point + index - (int)(&cmd_line[0])));
gFileFifo.reset();
transfer_frags = 0;
transfer_state = TRANSFER_BEGIN;
sprintf((char *)dbgStr, "Writing to file:%s\n", (char *)filePath);
net_print((const uint8_t *)dbgStr, strlen((const char *)dbgStr));
}
}
else
#endif
{
/*transfer gcode*/
//Serial.write(cmd_line, readNum);
if((strchr((const char *)cmd_line, 'G') != 0)
|| (strchr((const char *)cmd_line, 'M') != 0)
|| (strchr((const char *)cmd_line, 'T') != 0))
{
if(strchr((const char *)cmd_line, '\n') != 0 )
{
String gcode((const char *)cmd_line);
// sprintf((char *)dbgStr, "read %d: %s\n", readNum, cmd_line);
// net_print((const uint8_t *)dbgStr, strlen((char *)dbgStr));
if(gcode.startsWith("M998") && (M3_TYPE == ROBIN))
{
net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}
else if(gcode.startsWith("M997"))
{
if(gPrinterInf.print_state == PRINTER_IDLE)
// net_print((const uint8_t *) "M997 IDLE\r\n", strlen((const char *)"M997 IDLE\r\n"));
strcpy((char *)dbgStr, "M997 IDLE\r\n");
else if(gPrinterInf.print_state == PRINTER_PRINTING)
// net_print((const uint8_t *) "M997 PRINTING\r\n", strlen((const char *)"M997 PRINTING\r\n"));
strcpy((char *)dbgStr, "M997 PRINTING\r\n");
else if(gPrinterInf.print_state == PRINTER_PAUSE)
//net_print((const uint8_t *) "M997 PAUSE\r\n", strlen((const char *)"M997 PAUSE\r\n"));
strcpy((char *)dbgStr, "M997 PAUSE\r\n");
else
strcpy((char *)dbgStr, "M997 NOT CONNECTED\r\n");
// net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}
else if(gcode.startsWith("M27"))
{
memset(dbgStr, 0, sizeof(dbgStr));
sprintf((char *)dbgStr, "M27 %d\r\n", gPrinterInf.print_file_inf.print_rate);
// net_print((const uint8_t *) dbgStr, strlen((const char *)dbgStr));
// net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}
else if(gcode.startsWith("M992"))
{
memset(dbgStr, 0, sizeof(dbgStr));
sprintf((char *)dbgStr, "M992 %02d:%02d:%02d\r\n",
gPrinterInf.print_file_inf.print_hours, gPrinterInf.print_file_inf.print_mins, gPrinterInf.print_file_inf.print_seconds);
// net_print((const uint8_t *) dbgStr, strlen((const char *)dbgStr));
// net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}
else if(gcode.startsWith("M994"))
{
memset(dbgStr, 0, sizeof(dbgStr));
sprintf((char *)dbgStr, "M994 %s;%d\r\n",
gPrinterInf.print_file_inf.file_name.c_str(), gPrinterInf.print_file_inf.file_size);
// net_print((const uint8_t *) dbgStr, strlen((const char *)dbgStr));
// net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}
else if(gcode.startsWith("M115"))
{
memset(dbgStr, 0, sizeof(dbgStr));
if(M3_TYPE == ROBIN)
strcpy((char *)dbgStr, "FIRMWARE_NAME:Robin\r\n");
else if(M3_TYPE == TFT28)
strcpy((char *)dbgStr, "FIRMWARE_NAME:TFT28/32\r\n");
else if(M3_TYPE == TFT24)
strcpy((char *)dbgStr, "FIRMWARE_NAME:TFT24\r\n");
// net_print((const uint8_t *) dbgStr, strlen((const char *)dbgStr));
// net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}
/*else if(gcode.startsWith("M105"))
{
memset(dbgStr, 0, sizeof(dbgStr));
sprintf((char *)dbgStr, "T:%d /%d B:%d /%d T0:%d /%d T1:%d /%d @:0 B@:0\r\n",
(int)gPrinterInf.curSprayerTemp[0], (int)gPrinterInf.desireSprayerTemp[0], (int)gPrinterInf.curBedTemp, (int)gPrinterInf.desireBedTemp,
(int)gPrinterInf.curSprayerTemp[0], (int)gPrinterInf.desireSprayerTemp[0], (int)gPrinterInf.curSprayerTemp[1], (int)gPrinterInf.desireSprayerTemp[1]);
// net_print((const uint8_t *) dbgStr, strlen((const char *)dbgStr));
// net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
}*/
else
{
DEBUG_PRINT(F("GCODE COMMANDS "));
DEBUG_PRINTLN(gcode);
if(gPrinterInf.print_state == PRINTER_IDLE)
{
if(gcode.startsWith("M23") || gcode.startsWith("M24"))
{
gPrinterInf.print_state = PRINTER_PRINTING;
gPrinterInf.print_file_inf.file_name = "";
gPrinterInf.print_file_inf.file_size = 0;
gPrinterInf.print_file_inf.print_rate = 0;
gPrinterInf.print_file_inf.print_hours = 0;
gPrinterInf.print_file_inf.print_mins = 0;
gPrinterInf.print_file_inf.print_seconds = 0;
printFinishFlag = false;
}
}
gcodeM3.concat(gcode);
}
}
}
}
if(strlen((const char *)dbgStr) > 0)
{
net_print((const uint8_t *) "ok\r\n", strlen((const char *)"ok\r\n"));
net_print((const uint8_t *) dbgStr, strlen((const char *)dbgStr));
memset(dbgStr, 0, sizeof(dbgStr));
}
do_transfer();
yield();
}
if(gcodeM3.length() > 2)
{
package_gcode(gcodeM3, true);
//Serial.write(uart_send_package, sizeof(uart_send_package));
/*transfer_state = TRANSFER_READY;
digitalWrite(EspReqTransferPin, LOW);*/
do_transfer();
socket_busy_stamp = millis();
}
}
}
return true;
}
I wrote a function that isolated the code to call this function in the previous management zone and the new management of TCP messages.
{
if (tcp.hasClient()){
for(i = 0; i < MAX_SRV_CLIENTS; i++){
//find free/disconnected spot
#if 0
if (!serverClients[i] || !serverClients[i].connected()){
if(serverClients[i]) serverClients[i].stop();
serverClients[i] = tcp.available();
continue;
}
#else
if(serverClients[i].connected())
{
serverClients[i].stop();
}
#endif
serverClients[i] = tcp.available();
}
if (tcp.hasClient())
{
//no free/disconnected spot so reject
WiFiClient serverClient = tcp.available();
serverClient.stop();
}
}
memset(dbgStr, 0, sizeof(dbgStr));
for(i = 0; i < MAX_SRV_CLIENTS; i++)
{
if (serverClients[i] && serverClients[i].connected())
{
uint32_t readNum = serverClients[i].available();
if(readNum > FILE_FIFO_SIZE)
{
// net_print((const uint8_t *) "readNum > FILE_FIFO_SIZE\n");
serverClients[i].flush();
// Serial.println("flush");
continue;
}
if(readNum > 0)
{
char * point;
uint8_t readStr[readNum + 1] ;
uint32_t readSize;
readSize = serverClients[i].read(readStr, readNum);
readStr[readSize] = 0;
if (!manageMessage((char*)readStr, readSize)) break;
}
}
}
and here is the management in the WS listener.
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
DynamicJsonDocument docwsT(512);
DeserializationError error;
switch(type) {
case WStype_DISCONNECTED:
webSocket.sendTXT(num, "{\"connection\": false}");
DEBUG_PRINT(F(" Disconnected "));
DEBUG_PRINTLN(num, DEC);
isConnectedWebSocket = false;
// isConnectedWebSocketAck = false;
// DEBUG_PRINTF_AI(F("[%u] Disconnected!\n"), num);
break;
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(num);
// DEBUG_PRINTF_AI(F("[%u] Connected from %d.%d.%d.%d url: %s\n"), num, ip[0], ip[1], ip[2], ip[3], payload);
DEBUG_PRINT(num);
DEBUG_PRINT(F("Connected from: "));
DEBUG_PRINT(ip.toString());
DEBUG_PRINT(F(" "));
DEBUG_PRINTLN((char*)payload);
// send message to client
// webSocket.sendTXT(num, "{\"type\":\"connection\", \"connection\": true, \"simpleMessage\": "+String(readSingleMessage?"true":"false")+"}");
isConnectedWebSocket = true;
memset(dbgStr, 0, sizeof(dbgStr));
sprintf((char *)dbgStr, "FWV:%s\r\n", firmwareVersion);
net_print((const uint8_t*)dbgStr, strlen((const char *)dbgStr));
}
break;
case WStype_TEXT:
DEBUG_PRINT("NUM -> ");DEBUG_PRINT(num);
DEBUG_PRINT("payload -> ");DEBUG_PRINTLN((char*)payload);
manageMessage((char*)payload, length);
// manageMessage(String((char*)payload));
// error = deserializeJson(docwsT, (char*)payload);
//
// if (error) {
// // if the file didn't open, print an error:
// DEBUG_PRINT(F("Error parsing JSON "));
// webSocket.broadcastTXT("Error on WS");
// }else{
// JsonObject postObjws = docwsT.as<JsonObject>();
//
// bool startReceiveDevMsg = postObjws[F("startReceiveDevMsg")];
// if (startReceiveDevMsg==true){
//// readSingleMessage = postObjws[F("singleMessage")];
// isConnectedWebSocketAck = true;
// DEBUG_PRINT(F("Start listening messages SM -> "));
// DEBUG_PRINTLN(isConnectedWebSocketAck);
//
// webSocket.broadcastTXT("{\"type\": \"device_msg\", \"receiving\": true}");
// }else if (startReceiveDevMsg==false){
// isConnectedWebSocketAck = false;
// DEBUG_PRINT(F("Start listening messages SM -> "));
// DEBUG_PRINTLN(isConnectedWebSocketAck);
//
// webSocket.broadcastTXT("{\"type\": \"device_msg\", \"receiving\": false}");
// }
//
// bool singleMessage = postObjws[F("singleMessage")];
// DEBUG_PRINT(F("Single message -> "));
// DEBUG_PRINTLN(singleMessage);
// if (singleMessage){
// readSingleMessage = singleMessage;
// }
// }
// DEBUG_PRINTF_AI(F("[%u] get Text: %s\n"), num, payload);
// send message to client
// webSocket.sendTXT(num, "message here");
// send data to all connected clients
// webSocket.broadcastTXT("message here");
break;
case WStype_BIN:
//// DEBUG_PRINTF_AI(F("[%u] get binary length: %u\n"), num, length);
// hexdump(payload, length);
//
// // send message to client
// // webSocket.sendBIN(num, payload, length);
// break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
case WStype_PING:
case WStype_PONG:
// DEBUG_PRINTF_AI(F("[%u] get binary length: %u\n"), num, length);
DEBUG_PRINT(F("WS : "))
DEBUG_PRINT(type)
DEBUG_PRINT(F(" - "))
DEBUG_PRINTLN((char*)payload);
// send message to client
// webSocket.sendBIN(num, payload, length);
break;
}
}
Test WebSocket
You can connect with the simple WebSocket client that you can find in this article.
When the connection starts, you receive the temperature and WiFi information. You can try to add a command like M20 1:, pay attention to the return at the end (use shift + enter), and you receive a set of messages like
REST end points
By default, only one endpoint is exposed, the file upload.
To develop a Web Interface first, I will enable CORS requests. Refer to this tutorial “How to create a REST server on esp8266 or esp32: CORS request, OPTION, and POST“.
Where sendCrossOriginHeader is managed by ENABLE_CORS
define.
void setCrossOrigin(){
#ifdef ENABLE_CORS
server.sendHeader(F("Access-Control-Allow-Origin"), F("*"));
server.sendHeader(F("Access-Control-Max-Age"), F("600"));
server.sendHeader(F("Access-Control-Allow-Methods"), F("PUT,POST,GET,OPTIONS"));
server.sendHeader(F("Access-Control-Allow-Headers"), F("*"));
#endif
};
void sendCrossOriginHeader(){
DEBUG_PRINTLN(F("sendCORSHeader"));
server.sendHeader(F("access-control-allow-credentials"), F("false"));
setCrossOrigin();
server.send(204);
}
As you can see, It isn’t a multipart form data, but It wants a stream of the file in raw format.
void handleUpload()
{
DEBUG_PRINTLN(F("Upload request!"));
setCrossOrigin();
uint32_t now;
uint8_t readBuf[1024];
uint32_t postLength = server.getPostLength();
String uri = server.uri();
if(uri != NULL)
{
if((transfer_file_flag) || (transfer_state != TRANSFER_IDLE) || (gPrinterInf.print_state != PRINTER_IDLE))
{
server.send(409, FPSTR(STR_MIME_TEXT_PLAIN), FPSTR("409 Conflict"));
return;
}
if(server.hasArg((const char *) "X-Filename"))
{
if((transfer_file_flag) || (transfer_state != TRANSFER_IDLE))
{
server.send(500, FPSTR(STR_MIME_APPLICATION_JSON), FPSTR(STR_JSON_ERR_500_IS_BUSY));
return;
}
file_fragment = 0;
rcv_end_flag = false;
transfer_file_flag = true;
gFileFifo.reset();
upload_error = false;
upload_success = false;
String FileName = server.arg((const char *) "X-Filename");
//package_gcode(FileName, true);
//transfer_state = TRANSFER_READY;
//digitalWrite(EspReqTransferPin, LOW);
//String fileNameAfterDecode = urlDecode(FileName);
//package_gcode(fileNameAfterDecode, true);
//transfer_state = TRANSFER_READY;
//digitalWrite(EspReqTransferPin, LOW);
if(package_file_first((char *)FileName.c_str(), (int)postLength) == 0)
{
/*transfer_state = TRANSFER_READY;
digitalWrite(EspReqTransferPin, LOW);*/
}
else
{
transfer_file_flag = false;
}
/*wait m3 reply for first frame*/
int wait_tick = 0;
while(1)
{
do_transfer();
delay(100);
wait_tick++;
if(wait_tick > 20) // 2s
{
if(digitalRead(McuTfrReadyPin) == HIGH) // STM32 READY SIGNAL
{
upload_error = true;
// Serial.println("upload_error");
}
else
{
// Serial.println("upload_sucess");
}
break;
}
int len_get = get_printer_reply();
if(len_get > 0)
{
esp_data_parser((char *)uart_rcv_package, len_get);
uart_rcv_index = 0;
}
if(upload_error)
{
break;
}
}
if(!upload_error)
{
now = millis();
do
{
do_transfer();
int len = get_printer_reply();
if(len > 0)
{
// Serial.println("rcv");
esp_data_parser((char *)uart_rcv_package, len);
uart_rcv_index = 0;
}
if(upload_error || upload_success)
{
break;
}
if (postLength != 0)
{
uint32_t len = gFileFifo.left();
if (len > postLength)
{
len = postLength;
}
if(len > sizeof(readBuf))
{
len = sizeof(readBuf);
}
if(len > 0)
{
size_t len2 = server.readPostdata(server.client(), readBuf, len);
if (len2 > 0)
{
postLength -= len2;
gFileFifo.push((char *)readBuf, len2);
now = millis();
}
}
}
else
{
rcv_end_flag = true;
break;
}
yield();
}while (millis() - now < 10000);
}
if(upload_success || rcv_end_flag )
{
server.send(200, FPSTR(STR_MIME_APPLICATION_JSON), FPSTR(STR_JSON_ERR_0));
}
//if((millis() - now >= 10000) || upload_error)
else
{
//Serial.print("len:");
//Serial.println(gFileFifo.left() );
//Serial.print("postLength:");
//Serial.println(postLength );
if(Serial.baudRate() != 115200)
{
Serial.flush();
Serial.begin(115200);
// Serial.begin(4500000);
}
//Serial.println("timeout" );
transfer_file_flag = false;
rcv_end_flag = false;
transfer_state = TRANSFER_IDLE;
server.send(500, FPSTR(STR_MIME_APPLICATION_JSON), FPSTR(STR_JSON_ERR_500_NO_DATA_RECEIVED));
}
}
else
{
server.send(500, FPSTR(STR_MIME_APPLICATION_JSON), FPSTR(STR_JSON_ERR_500_NO_FILENAME_PROVIDED));
return;
}
}
}
I also add a new endpoint in GET and POST to manage the configuration of BeePrint:
server.on("/configApp", HTTP_OPTIONS, sendCrossOriginHeader);
server.on("/configApp", HTTP_POST, postConfigFile, NULL);
server.on("/configApp", HTTP_GET, getConfigFile, NULL);
It stores a file on SPIFFS that can be used to preserve the configuration of BeeTree UI.
void postConfigFile() {
DEBUG_PRINTLN(F("postConfigFile"));
setCrossOrigin();
uint32_t postLength = server.getPostLength();
if(postLength > maxPostSize || (postLength <= 0))
{
server.send(400, FPSTR(STR_MIME_TEXT_PLAIN), FPSTR("Bad Request, wrong post size"));
return;
}
uint8_t readBuf[postLength];
DynamicJsonDocument doc(postLength);
if((postLength > sizeof(readBuf)) || (postLength <= 0))
{
server.send(400, FPSTR(STR_MIME_TEXT_PLAIN), FPSTR("Bad Request"));
return;
}
server.readPostdata(server.client(), readBuf, postLength);
// serializeJson(doc, buf);
// JsonObject& root = jsonBuffer.parseObject((char *)readBuf);
//
// root = jsonBuffer.parseObject((char *)readBuf);
DeserializationError error = deserializeJson(doc, readBuf);
String postBody = server.arg("plain");
DEBUG_PRINTLN(postBody);
// DynamicJsonDocument doc(CONFIG_FILE_HEAP);
// DeserializationError error = deserializeJson(doc, postBody);
if (error) {
// if the file didn't open, print an error:
DEBUG_PRINT(F("Error parsing JSON "));
DEBUG_PRINTLN(error.c_str());
String msg = error.c_str();
server.send(400, F("text/html"), "Error in parsin json body! <br>"+msg);
}else{
JsonObject postObj = doc.as<JsonObject>();
DEBUG_PRINT(F("HTTP Method: "));
DEBUG_PRINTLN(server.method());
if (server.method() == HTTP_POST) {
if (( postObj.containsKey("server") ||
postObj.containsKey("preferences") ||
postObj.containsKey("serverSMTP") ||
postObj.containsKey("camera")
)) {
DEBUG_PRINT(F("Open config file..."));
File configFile = SPIFFS.open(F("/mc/config.txt"), "w");
if (!configFile) {
DEBUG_PRINTLN(F("fail."));
server.send(304, F("text/html"), F("Fail to store data, can't open file!"));
}else{
DEBUG_PRINTLN(F("done."));
serializeJson(doc, configFile);
// httpRestServer.sendHeader("Content-Length", String(postBody.length()));
server.send(201, F("application/json"), postBody);
// DEBUG_PRINTLN(F("Sent reset page"));
// delay(5000);
// ESP.restart();
// delay(2000);
}
}
else {
server.send(204, F("text/html"), F("No data found, or incorrect!"));
}
}
}
}
Test Upload
The upload process can be managed by curl command like this:
curl -i -X POST "http://192.168.1.164/upload?X-Filename=prova.stl" -H "Content-Type: text/xml" --data-binary "@FBG5_prova.gcode"
And here is the response:
* Trying 192.168.1.164... * TCP_NODELAY set * Connected to 192.168.1.164 (192.168.1.164) port 80 (#0) > POST /upload?X-Filename=prova.stl×tamp=1635695248382 HTTP/1.1 > Host: 192.168.1.164 > User-Agent: curl/7.55.1 > Accept: */* > Content-Type: text/xml > Content-Length: 299092 > Expect: 100-continue > * Done waiting for 100-continue * We are completely uploaded and fine * HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Cache-Control: no-cache, no-store, must-revalidate < Pragma: no-cache < Expires: 0 < Content-Type: application/json < Content-Length: 9 < Connection: close < {"err":0}* Closing connection 0
Compile mischianti version of the MKS WiFi firmware
Now we must compile the Mischianti MKS WiFi version of the firmware. As described in the previous article, you can upload it directly to the MKS WiFi board or NodeMCU device.
First, you must use the 2.7.4 version of esp8266 core because I continue to use the SPIFFS filesystem like the original version.
Then you must set this value to your Arduino IDE:
- Board: NodeMCU 1.0 (ESP-12E Module)
- Builtin Led: 2
- Upload Speed: 921600 (115200 is more secure)
- CPU Frequency: “160MHz” (80MHZ is more secure)
- Flash Size: 4MB
- SPIFFS: 3Mb
And my last build used this set of library
- ArduinoJson@6.18.4
- ESP8266WiFi@1.0
- ESP8266mDNS@1.2
- EEPROM@1.0
- ESP8266HTTPClient@1.2
- WebSockets@2.3.5
Activate CORS and DEBUG
To simplify the development of the firmware, I add two define:
#define ENABLE_CORS
that allows you to use an external web interface (not installed on the device), you can get more information by reading the REST tutorial.
#define MKSWIFI_DEBUG
That enable some debug information on a specified Serial
// Define where debug output will be printed.
#define DEBUG_PRINTER Serial1
with this configuration, you can read debug messages on the D4 pin, and you can get more information on this article “WeMos D1 mini (esp8266), debug on secondary UART“.
Generate FileSystem binary file
To get fully working, you must also generate a binary file of Filesystem.
Add verbose output to Arduino IDE
To better understand all processes, we will enable verbose output on our Arduino IDE. You can find these options on File -> Preferences
and check Show verbose output
checks.
Now we can grab and reuse console commands.
Prerequisite
For the Filesystem, we can do the same, but first, you need to read the following guides WeMos D1 mini (esp8266), integrated SPIFFS Filesystem.
We will add the data directory to the sketch folder (with some files) and use the plugin to upload.
In the console, we find the correct command to generate this file.
We can now see a lot of information, including the file’s location and the address.
Using Web Interface or SD to upload
Now with the Web Interface, you can follow these steps to upload
- Take the MksWifi_WebView.bin and upload the Web View;
- Take MksWifi.bin and upload the firmware.
It’s essential to follow these steps because my firmware version needs more resources, and if you upload firmware first, you can’t upload the Filesystem.
So in the future, if you want to upload a new version of Filesystem, you must upload the older version of the firmware and repeat the process.
You can download pre-compiled firmware of the Mischianti version:
You can download pre-compiled original firmware from here:
MksWifi.bin
here;If you have firmware like Flying Bear Ghost 5, you can put these files inside the SD, insert It in the printer, restart It, wait until the first process is complete, then continue again to upload the remaining file.
Thanks
- MKS WIFI for Makerbase Robin: boards and how to wiring esp12 & NodeMCU
- MKS WIFI for Makerbase Robin: PCB and how to compile & upload firmware
- MKS WIFI for Makerbase Robin: communication protocol and Cura plugin
- MKS WIFI for Makerbase Robin: firmware upgrade and new Web Socket features
- MKS WIFI for Makerbase Robin: BeePrint web interface with Camera on Flying Bear Ghost
upload blocked at 40%, page white….very interesting plugins and looks nice…tnx
Hi Lazar,
Hehehe..
upload what? From usb? Sd? Web? And whitch part? plugin?
Bye Renzo
i did this but when i try to go to 1.1.1.1/#/home for example i get a 404 eror but the ‘update works fine any help wpild be awesome
Hi Zig,
are you sure that 1.1.1.1 (tha is a public IP) is the IP of your printer?
Bye Renzo
Hello great work I uploaded it on my MKS DLC 2.1 and it works! Maybe you can share it on github then you’ll have more support. So far this is the best I’ve seen on the web MKS technically. Are you also working on a CNC version because I have this version.
Greetings and keep it up!
Hi Raini,
It’s wonderful.
I released the firmware on GitHub, but I’d like to find some collaborators for the Web interface first, then I’ll open It on GitHub.
The Web project Is not so simple, and giving support and checking the development needs a lot of time.
Bye Renzo
Excellent work!
There are a couple of wishes: The ability to change some parameters (temperature, blowing) after the start of printing. Or at least send a G-code.
Also incorrect Russian characters on the screen (I can’t add a photo here.)
Hi Vitaly,
I add the widget to send GCODE, but I disable it during printing, I must check if It can work.
Please open a topic and attach the screenshot.
You can also verify the translation in this file.
Thanks give me feedback Renzo
Something is wrong the DynamicJsonDocument is not a valid type.
Hi Nayef,
You can find information on how to compile the project in the relative article.
Bye Renzo
Hi I uploaded everything according to the video and using the prepared .bin files but I cannot connect to the printer. The homepage appears and everything looks okay but it won’t connect. Any ideas or workarounds? Board: MKS Robin E3P with the ESP32 Wifi module
Hi jon,
Do you have a modded firmware or standard?
BeePrint on Robin E3D
Other people have experience with that board.
Bye Renzo
Bonjour @Renzo et d’abord merci.
J’ai réussi à ajouter une caméra (non ESP32) mais je ne peux pas redimensionner la frame dédiée, aurais-tu une idée du pourquoi s’il te plait
No mi spiace, mi dovresti dare più informazioni, nel caso apri un topic sull’apposito forum.
Ciao RM
Hello,
I have a Flying Bear Ghost 5 and I installed your extension.
After it worked for 3 days, it suddenly stopped working.
I tried again simply to reinstall the two files, but the error persists
The web interface works and I can home the printer.
When I select file and upload it, the website turns gray and nothing else happens. The printer display then shows an error.
The file hasn’t been copied to the SD card either.
If I copy the file on the computer to the SD card and use the SD card on the printer, I cannot start the printer via the browser. But directly on the display.
I also tried flashing the original firmware from Flying Bear, but the web interface remains Beeprint’s.
Help. Can you help? How can I go back to the original firmware if necessary and try again.
Thank you Andre
(Translated with google translate)
Hi,
It’s possible that the sd is corrupted, try to format it.
Bye Renzo
Hello, thanks for the quick feedback. 🙂
I will even use a new SD 😉
Can I get both files from here:
https://github.com/xreef/MKS_WIFI_upgrade_with_BeePrint_web_interface/raw/master/firmware_release/MksWifi.bin
https://github.com/xreef/MKS_WIFI_upgrade_with_BeePrint_web_interface/raw/master/firmware_release/MksWifi_WebView.bin
may simultaneously copy the files to the SD, insert them into the printer and restart the printer twice. Or one after the other?
So first
Copy MksWifi_WebView.bin to the card and turn on the printer.
Then delete the file and then copy MksWifi.bin to the card and restart the printer. ?
If it was successful, should the files be deleted from the card again?
Thank you Andre
Hi Andre,
you can copy all the files in the SD and then restart 2 times the printer, if the firmware was uploading the file was renamed in bak.
Bye Renzo
Hallo,
it works again. 🙂
Hehehe.. perfect!
Time solves all problems 😛
Hi I uploaded webUI and than Firmware. If I go to 192.168.3.53/update it looks as in video.
When I try to go to 192.168.3.53/#/home or any other address I get 404 message like this: {“err”: “404: / NOT FOUND”}
I used precompiled code that You provided here on this website.
I am using MKS Robin WiFi v1.1
Hi Thomas,
try to reupload from beginning as described in the guide.
Bye Renzo
hi,
i use esp-07 and wire same pinout like esp wifi module
i use mks robin nano v1.3 and two trees sapphire pro
i uploaded wifi bin file via sd card but alwys says wifi is being configured
best..
Hi Deniz,
I don’t know what the issue might be, but I suggest opening a topic in the forum. If you could include details about the wiring and every step you’ve followed, it would help us understand and diagnose the problem more effectively.
Bye Renzo
Hi Renzo,
Thank you for answer..
do i need update firmware esp-07 board?
i upload firmware mks robin card via sd card and changed file name correctly.and esp-07 card works normaly.blinks leds normal.
when i enter wifi from main menu, ‘wifi is being configured please wait’ message is appearing always
Hi deniz,
sure, you must upload my firmware so the esp07.
You can follow these steps.
MKS WIFI for Makerbase Robin: firmware upgrade and new Web Socket features – 4
Bye Renzo
Please help me assemble JGMAKER Artist D Pro with MKS-Robin-Pro 1.0 for MKS-WIFI Please
Hi Nikolay,
Sorry, I have only experience with Ghost 5, so I don’t know with the hardware you have.
Bye Renzo