Máy chủ web của tôi đã hoạt động rất tốt trong nhiều tháng khi được kết nối với Linux thông qua cổng gốc.
Nhưng khi được kết nối với Windows 10 thông qua cổng gốc, nếu máy chủ web Arduino không hoạt động trong khoảng 5 phút (khi không có máy khách nào gọi trang web), thì sẽ có độ trễ 5-10 giây trước khi trang web có thể tải. Sự chậm trễ này không xảy ra khi được kết nối với máy chủ web thông qua cổng lập trình.
Có vẻ như Windows có thể đặt cổng ở chế độ ngủ khi nhận thấy độ trễ không hoạt động, và sau đó phải chờ cổng thức dậy trước khi có thể gọi trang web.
Trên Windows "Cài đặt nguồn", tôi đặt máy tính không bao giờ chuyển sang chế độ ngủ và trong Nguồn "Cài đặt nâng cao", tôi đã tắt "tạm dừng chọn lọc" USB.
Bạn có biết tại sao chỉ có sự chậm trễ kỳ lạ này trên Windows và chỉ khi được kết nối qua cổng gốc không?
PHỤ LỤC: Tôi đã tạo một ví dụ đơn giản tái tạo vấn đề trên máy của tôi. Tôi tự hỏi nếu bất cứ ai có thể thấy bất kỳ vấn đề với mã này.
Đầu tiên, mã trăn. Lưu ý rằng nếu tập lệnh python không bao giờ chạy, không có độ trễ trên máy chủ web Arduino và mọi thứ hoạt động như mong đợi.
import serial, sys
SERIALPORT = "COM5" # Change this to your serial port!
# Set up serial port
try:
ser = serial.Serial(SERIALPORT, 115200, timeout=0)
except serial.SerialException:
sys.exit()
ser.write("Hello World")
print("Hello World")
ser.close()
Và dưới đây là mã Arduino đơn giản hóa. Nó chỉ là một máy chủ web đơn giản phục vụ một trang có nút "tải lại" để tải lại trang. Bạn có thể nhấn "tải lại" bao nhiêu lần tùy ý và chương trình không bao giờ bị đóng băng. Nhưng nếu bạn chạy mã python ở trên và sau đó thử tải lại trang, sẽ có độ trễ dài (khoảng 10-60 giây theo ước tính hiện tại của tôi).
Nếu bạn nhận xét tất cả các dòng "SerialUSB.print" ở bất kỳ đâu trong vòng lặp (trong trường hợp đơn giản này, chỉ có 1 dòng tại: "SerialUSB.println (data);" trong hàm processData), thì trang web không bao giờ đóng băng, ngay cả khi bạn chạy mã python thường xuyên.
Trong ví dụ thực tế của tôi, mã trăn của tôi đã chạy một lần một phút, gây ra đóng băng ngẫu nhiên. Nếu tôi dừng mã python chạy, thì trang web sẽ không còn bị đóng băng nữa. Cuối cùng tôi đã bình luận tất cả các câu lệnh SerialUSB.print của tôi trong vòng lặp và bằng cách đó tôi có thể có mã python chạy đúng lịch trình và chương trình của tôi có đầy đủ chức năng (ngoại trừ việc mất serialUSB.print).
#include <Ethernet.h>
byte mac[] = {
0x04, 0xBA, 0xB0, 0xCC, 0xDF, 0x04
};
EthernetServer server(80);
EthernetClient client;
const byte MAX_INPUT = 25; //for processIncomingByte
void setup ()
{
SerialUSB.begin (115200);
Ethernet.begin(mac);
SerialUSB.print("server is at ");
SerialUSB.println(Ethernet.localIP());
} // end of setup
bool processIncomingByte (const byte inByte)
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;
switch (inByte)
{
case '\n': // end of text
input_line [input_pos] = 0; // terminating null byte
if (input_pos == 0)
return true; // got blank line
// terminator reached! process input_line here ...
processData (input_line);
// reset buffer for next time
input_pos = 0;
break;
case '\r': // discard carriage return
break;
default:
// keep adding if not full ... allow for terminating null byte
if (input_pos < (MAX_INPUT - 1)) input_line [input_pos++] = inByte;
break;
} // end of switch
return false; // don't have a blank line yet
} // end of processIncomingByteWeb
void processData (const char * data)
{ //Note: since there are no GET requests in this simple example, I removed the parts for processing GET.
SerialUSB.println (data);
if (strlen (data) < 4)
return;
} // end of processDataWeb
void loop ()
{
client = server.available();
if (client) {
boolean done = false;
while (client.connected() && !done)
{
while (client.available () > 0 && !done)
done = processIncomingByte (client.read ());
} // end of while client connected
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><body>");
client.print("<a href=\"/\">Reload</a></body></html>");
delay(10); client.stop();
}
} // end of loop
Đây không phải là vấn đề về mặt kỹ thuật đối với tôi nữa, ngoại trừ việc phải bình luận tất cả các tuyên bố "SerialUSB.print" của tôi. Nhưng tôi quan tâm đến việc tìm hiểu những gì gây ra hành vi kỳ lạ này.
Lưu ý: các chức năng "processIncomeByte" và "processData" chủ yếu là từ các bài viết và hướng dẫn của ông Gammon và chúng hoạt động hoàn hảo cho tôi trong 2 máy chủ web Arduino khác mà tôi đang chạy. Tôi muốn lưu ý điều này bởi vì nếu tôi đã tự viết các chức năng, thì rõ ràng chúng sẽ đòi hỏi sự xem xét kỹ lưỡng hơn nhiều.