RS232桥接WiFi ESP32问题。如何避免串口中的随机数据?

问题描述 投票:0回答:1

首先,如果有人能帮助我,谢谢。 澄清一下,我不是专家,欢迎任何帮助/批评。 我与之通信的硬件不是 ESP32,它是一个具有连接接口的板。 我尝试将涉及的代码部分放在一起以便更好地理解。 程序期望通过套接字接收一个字符串并将其记录在串行中,依次打印响应。

所用材料:

  • ESP32-E。
  • Rs232转tll商用模块,带max232芯片。
  • USB-rs232 适配器,用于使用 putty 和 python 进行测试。
  • 空调制解调器母-母适配器。

进行的测试:

  • 用腻子连接。
  • 与python脚本连接。
  • 使用逻辑分析仪查看流量。

问题:

  • 当我从 Putty 或 python 脚本与 USB 适配器和空调制解调器适配器连接时,一切都按预期工作。

  • 当我连接到 esp32 脚本时,我会收到所传输内容的“回声”,并且附加字符会随机记录在序列中。我用逻辑分析仪查了一下,确实是这样。它并不总是发生,它在 80% 的时间内按预期工作,但因此并不可靠。

  • 据观察,如果我不以较小的延迟逐个字符地记录,硬件将无法识别该字符串。

观察:

  • 它不使用 DSR 或 RTS,因为它们在 python 脚本中设置为 False 并且完美运行。
  • 虽然最初在 esp 中使用 nullmodem 来映射 RX/Tx 引脚,但原则上我认为不使用其他控制信号不会影响我。
  • 起初我用互斥体将一个写入任务和另一个读取任务分开,但性能下降了,我发现其中的所有内容都更加高效。

腻子配置:

下面是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() {}

非常感谢你

c++ serial-port esp32 freertos arduino-esp32
1个回答
0
投票

嗯,想了想,我记得 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.