首先,如果有人能帮助我,谢谢。 澄清一下,我不是专家,欢迎任何帮助/批评。 我与之通信的硬件不是 ESP32,它是一个具有连接接口的板。 我尝试将涉及的代码部分放在一起以便更好地理解。 程序期望通过套接字接收一个字符串并将其记录在串行中,依次打印响应。
所用材料:
进行的测试:
问题:
当我从 Putty 或 python 脚本与 USB 适配器和空调制解调器适配器连接时,一切都按预期工作。
当我连接到 esp32 脚本时,我会收到所传输内容的“回声”,并且附加字符会随机记录在序列中。我用逻辑分析仪查了一下,确实是这样。它并不总是发生,它在 80% 的时间内按预期工作,但因此并不可靠。
据观察,如果我不以较小的延迟逐个字符地记录,硬件将无法识别该字符串。
观察:
下面是Python代码。
import serial
import time
import threading
import sys
port = '/dev/ttyUSB0'
baudrate = 9600
byte_size = serial.EIGHTBITS
parity = serial.PARITY_NONE
stop_bits = serial.STOPBITS_ONE
ser = serial.Serial(port, baudrate, bytesize=byte_size, parity=parity, stopbits=stop_bits, timeout=2,dsrdtr=False,rtscts=False)
lock = threading.Lock()
#write thread
def sendBytes():
global lock
with lock:
ser.write(b'\x03')
ser.flush()
time.sleep(0.1)
while True:
user_input = input("\nInput the string to serial: \n")
if user_input.lower() == 'exit':
print("exit program.")
sys.exit(0)
with lock:
if 'r'==user_input or user_input=='reset' :
ser.write(b'\x03')
ser.flush()
else:
ser.write((user_input + '\r').encode())
ser.flush()
#read thread
def printData():
global lock
while True:
data = ser.read_all()
if data:
cleaned_data = data.replace(b'\n', b'').replace(b'\r', b'')
print(cleaned_data.decode('utf-8'))
time.sleep(0.08)
taskRead = threading.Thread(target=printData)
taskWrite = threading.Thread(target=sendBytes)
taskRead.start()
taskWrite.start()
ESP32代码:
// custom struct to manage messages to queue
typedef struct
{
char str[100];
int length;
}fixed_string_t;
// initzialice the socketserver
esp_err_t initServer(void)
{
ws.begin();
ws.onEvent(webSocketEvent);
return ESP_OK;
}
// task for websocket loop
void runWebSocketServer(void *pv)
{
for (;;)
{
ws.loop();
vTaskDelay(5 / portTICK_RATE_MS);
}
}
esp_err_t pushToRs2Queue(fixed_string_t q)
{
BaseType_t result = xQueueSend(rs232_queue, &q, portMAX_DELAY);
return result == ESP_OK ? ESP_OK : -1;
}
// manage websocket incoming messages
void webSocketEvent(uint8_t client, WStype_t type, uint8_t *data, size_t len)
{
if (type == WStype_TEXT)
{
std::string data_str(reinterpret_cast<const char *>(data), len);
fixed_string_t item;
strncpy(item.str, data_str.c_str(), sizeof(item.str) - 1);
//ensure null termination
item.str[sizeof(item.str) - 1] = '\0';
item.length = data_str.length();
pushToRs2Queue(item);
}
}
// Start o reset the connection with HW
void resetConn(void)
{
Serial2.write(0x03);
vTaskDelay(200 / portTICK_PERIOD_MS);
Serial2.flush();
}
// reader and writter task
void readRs232(void *pvp)
{
QueueHandle_t rs232_queue = (QueueHandle_t)pvp;
resetConn();
Serial2.setTimeout(100);
for (;;)
{
fixed_string_t arr;
if (xQueueReceive(rs232_queue, &arr, pdMS_TO_TICKS(50)) == pdTRUE)
{
string toWrite = arr.str;
if (!toWrite.empty() && toWrite[0] == 'c')
{
resetConn();
}
else
{
for (const char &c : toWrite)
{
Serial2.write(c);
vTaskDelay(35 / portTICK_PERIOD_MS);
}
// line feeder
Serial2.write(0x0D);
}
}
int bufferLen = Serial2.available();
if (bufferLen)
{
Serial.println(Serial2.readString());
}
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
void setup()
{
Serial.begin(115200);
while (!Serial)
;
ConnectWiFi_STA();
if (initServer() == ESP_OK)
{
xTaskCreatePinnedToCore(&runWebSocketServer, "websocket_server", 5048, NULL, 5, NULL, 1);
}
Serial2.begin(9600, SERIAL_8N1, TXD2, RXD2);
while (!Serial2);
xTaskCreatePinnedToCore(&readRs232, "readRs2", 10048, rs232_queue, 10, &rs232ReadHandle, tskNO_AFFINITY);
}
void loop() {}
非常感谢你
嗯,想了想,我记得 CAN BUS 通信也发生过类似的事情。 避免使用 Arduino 实现(串行类)并使用 ESP-IDF 实现,它工作得很好,它不再发送随机字节,它正确触发事件等。 我不知道是因为它是专门针对硬件的还是因为它对硬件有更多的控制权,但它工作得很好。
我留下了一个示例代码,以防有人遇到这种情况并且感兴趣。
void read_tsk(void *pvParameters)
{
// task containing a queue to print in a decoupled manner
toDebug("STarted");
uart_event_t event;
uint8_t *data = (uint8_t *)malloc(1024); // data buffer
resetConn();
for (;;)
{
if (xQueueReceive(xRS232Queue, (void *)&event,
portMAX_DELAY))
{
switch (event.type)
{
// data received
case UART_DATA:
{
uart_read_bytes(UART_NUM_1, data, event.size,
portMAX_DELAY);
std::string receivedData(reinterpret_cast<char *>
(data), event.size);
toDebug(receivedData.c_str());
break;
}
// Manage rest of events
case UART_BREAK:
case UART_PARITY_ERR:
case UART_FRAME_ERR:
default:
break;
}
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
free(data);
vTaskDelete(NULL);
}
esp_err_t selectRS2Config(void)
{
bool installed = false;
const uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE};
// Config uart params and pins no DSR no RTS
uart_param_config(UART_NUM_1, &uart_config);
uart_set_pin(UART_NUM_1, RXD2, TXD2, UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE);
// install driver
if (uart_driver_install(UART_NUM_1, 1024 * 2, 1024 * 2, 10,
&xRS232Queue, 0) == ESP_OK)
{
toDebug("Driver installed,launching task");
installed = true;
}
else
{
toDebug("Uart driver cannot install", true, ERROR_D);
}
if (installed)
{
xTaskCreatePinnedToCore(read_tsk, "read_tsk", 4096, NULL,
12,
&rs232ReadHandle, tskNO_AFFINITY);
return ESP_OK;
}
return -1;
}