Detection and bugfix procedures for S2E modules
An automated program for detection and error correction of an S2E module based on W5100S-EVB-PICO.
The Hong Kong office needs to inspect the S2E modules after they receive them from the manufacturer. Generally, random inspections will be conducted to check whether the module information matches and whether there are production errors.
This requires a detection program to assist. We decided to write an automation program based on W5100S-EVB-PICO. The program requirements is:
1. Automatically check all parameters, mainly MAC address and SN number;
2. Ability to automatically correct information errors when encountered;
3. Simple serial Ethernet communication test.
Cable Connection:
First define an array to store all S2E module information.
struct S2E_DATA {
char SERH[4];
uint8_t MAC[6];
uint8_t DEVICE_ID[16];
uint8_t STATE;
uint8_t SW_VER[2];
char DEVICE_TYPE[16];
char DEVICE_NAME[16];
char DEVICE_PWD[16];
uint16_t HTTP_PORT;
uint32_t FW_LEN;
uint32_t FW_CHECKSUM;
uint8_t DEBUG_FLAG;
uint8_t ECHO_FLAG;
uint8_t NETBIOS;
uint8_t DHCP;
uint8_t LOCAL_IP[4];
uint8_t SUBNET[4];
uint8_t GATEWAY[4];
uint8_t DNS[4];
uint8_t BAUDRATE;
uint8_t DATABIT;
uint8_t PARITY;
uint8_t STOPBIT;
uint8_t FLOWCONTROL;
uint8_t MODE;
uint16_t LOCAL_PORT;
uint8_t REMOTE_IP[4];
uint16_t REMOTE_PORT;
uint8_t DNS_FLAG;
char DOMAIN[32];
uint16_t INACTIVITY;
uint16_t RECONNECT;
uint16_t NAGLE_TIME;
uint16_t PACK_LEN;
uint16_t KEEP_ALIVE;
uint8_t BIND_PORT;
uint8_t LINK_CLEAR_BUF;
uint8_t LINK_PWD;
uint8_t LINK_MSG;
uint8_t LINK_CONDITION;
uint8_t START_MODE;
uint16_t CRC16;
uint32_t NET_SEND_NUM;
uint32_t NET_RCV_NUM;
uint32_t SEC_SEND_NUM;
uint32_t SEC_RCV_NUM;
uint32_t ON_TIME;
uint8_t RUN_MODE;
uint8_t TEMPERATURE;
};
RP2040 has two type serial ports, one is hardware UART and the other is software UART. The advantage of SoftwareSerial is that it can use any IO of RP2040.
SoftwareSerial W7500S2E_UART(1, 0);
There are two main data sources for information errors. One is from the module power-on message, and the other is that it can be judged from the received UDP response message through UDP "Discovery" broadcast.
S2E power-on message sample:
15:13:34.128 -> Device Name:W7500S2E-R1
15:13:34.874 -> MAC:00.08.DC.36.B9.7A
15:13:34.920 -> Firmware Version:2.9
15:13:34.920 -> Current Mode:AT-Command Mode
15:13:34.920 -> IP:192.168.1.88
15:13:34.920 -> SN:255.255.255.0
15:13:34.920 -> GW:192.168.1.1
15:13:34.920 -> DNS:114.114.114.114
Determine that the module has been initialized based on the power-on information and look for the "114" at the end of the power-on message.
case POWER_UP_W7500S2E:
{
//digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
while (W7500S2E_UART.available())
{
char a = W7500S2E_UART.read();
Serial.print(a);
data_String += a;
//Serial.print(data_String.indexOf("114\r\n"));
if(data_String.indexOf("114\r\n")!= -1)
{
w7500s2e_mac = data_String.substring((data_String.indexOf("MAC:")+strlen("MAC:")),data_String.indexOf("\r\nFirm"));
Serial.print("ok");
data_String = "";
W7500S2E_UART.flush();
delay(3000);
W7500S2E_UART.println("AT+SN?");
CurrentState = GET_W7500S2E_INFO;
}
}
}
break;
Determine whether the device's MAC, SN and other data are incorrect.
case CHECK_W7500S2E_SN:
{
while (W7500S2E_UART.available())
{
char a = W7500S2E_UART.read();
Serial.print(a);
data_String += a;
}
if(data_String.indexOf("OK\r\n")!= -1)
{
W7500S2E_UART.flush();
data_String = "";
CurrentState = POWER_UP_W7500S2E;
}
}
break;
Get all module information and automatically correct it if there is an error in the "SN".
case GET_W7500S2E_INFO:
{
digitalWrite(LED_BUILTIN, 0);
while (W7500S2E_UART.available())
{
char a = W7500S2E_UART.read();
Serial.print(a);
data_String += a;
}
if(data_String.indexOf("OK\r\n")!= -1)
{
//data_String = "";
w7500s2e_sn = data_String.substring(data_String.indexOf("[SN] Value is:")+strlen("[SN] Value is:"),data_String.indexOf("OK")-2);
Serial.println(w7500s2e_sn);
data_String = "";
W7500S2E_UART.flush();
w7500s2e_sn = "240425-"+ w7500s2e_mac.substring(9,11)+w7500s2e_mac.substring(12,14)+w7500s2e_mac.substring(15,17);
W7500S2E_UART.println("AT+<WIZNET>&DSN="+w7500s2e_sn);
w7500s2e_sn = "";
w7500s2e_mac = "";
CurrentState = CHECK_W7500S2E_SN;
}
}
break;
UDP info message:
The config tool of the S2E module uses UDP broadcast to send the search message "SERH" to (255.255.255.255). After receiving the "SERH" message, the S2E series module will respond to its own module information by broadcast(255.255.255.255).
server.begin(); // start the server
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
udp.begin(8888);
sendBroadcastPacket()
void sendBroadcastPacket() {
char data[] = "SERH"; // Discovery String
udp.beginPacket(broadcastIp, 1460); // open udp socket
udp.write(data); // Write your data to the packet
udp.endPacket(); // end
Serial.println("Discovery packet sent.");
}
After the module Reset, obtain all parameters through the printReceivedPackets function and determine whether there are any errors.
void printReceivedPackets() {
startTime = millis();
while (millis() - startTime < 500) {
int packetSize = udp.parsePacket();
if (packetSize) {
int len = udp.read((byte*)&s2eData, sizeof(s2eData) - 1);
if (len > 0) {
for(uint8_t m=0; m<16; m++)
{
if((s2eDataArray[m].MAC[3] != s2eData.MAC[3])||(s2eDataArray[m].MAC[4] != s2eData.MAC[4])||(s2eDataArray[m].MAC[5] != s2eData.MAC[5]))
{
memcpy(&s2eDataArray[count], &s2eData, sizeof(s2eData));
Serial.print("Module NO.");
Serial.print(count+1);
Serial.print(" [");
Serial.print(s2eDataArray[count].DEVICE_TYPE);
Serial.print("] ");
Serial.print("[MAC]:");
for (int i = 0; i < 6; i++) {
Serial.printf("%02X",s2eDataArray[count].MAC[i]);
if(i<5)
{
Serial.print(":");
}else{
Serial.print(" ");
break;
}
}
Serial.print("[IP]:");
for (int n = 0; n < 4; n++) {
Serial.print(s2eDataArray[count].LOCAL_IP[n]);
if(n<3)
{
Serial.print(".");
}else{
break;
}
}
Serial.print(" [Run Time]: ");
Serial.print(s2eDataArray[count].ON_TIME/(60*60*24));
Serial.print("d/");
Serial.print((s2eDataArray[count].ON_TIME/(60*60))%24);
Serial.print("h/");
Serial.print((s2eDataArray[count].ON_TIME/(60))%60);
Serial.print("m/");
Serial.print((s2eDataArray[count].ON_TIME)%60);
Serial.println("s");
count ++;
break;
}
}
}
}
}
}