serialport / serialport-rs

A cross-platform serial port library in Rust. Provides a blocking I/O interface and port enumeration including USB device information.
Other
478 stars 115 forks source link

Serial port operation has different performance in (windows10 \ MacOS) #196

Closed 3Q- closed 2 months ago

3Q- commented 3 months ago

The purpose of setting a timeout when using serialport scratch for serial communication is to prevent read operations from waiting indefinitely when no data arrives. If there is data, respond immediately and reset the timeout time. It is normal for me in MAC OS, but in Windows 10 system, even if there is data, I still need to wait until the timeout is reached before obtaining the data for the second read

use serialport;
use std::io::{self, Read, Write};
use std::thread;
use std::time::Duration;

use std::{
    // collections::HashMap,
    sync::{
        // mpsc::{Receiver, Sender, TryRecvError},
        Arc,
        Mutex,
    },
};

macro_rules! log {
    ($($arg:tt)*) => {
        println!(
            "{} ==> {}",
            chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f"),
            format_args!($($arg)*)
        )
    };
}

fn main() {
    println!("Please press enter key:");

    let port_path = "COM1";
    let port = serialport::new(port_path, 115_200)
        .parity(serialport::Parity::None)
        .data_bits(serialport::DataBits::Eight)
        .stop_bits(serialport::StopBits::One)
        .flow_control(serialport::FlowControl::None)
        .timeout(Duration::from_millis(3000))
        .open()
        .unwrap();

    let shared_port = Arc::new(Mutex::new(port));

    let read_port = Arc::clone(&shared_port);

    let read_thread = thread::spawn(move || {
        let mut serial = read_port.lock().unwrap().try_clone().unwrap();
        loop {
            let mut buffer = [0u8; 2048];
            match serial.read(&mut buffer) {
                Ok(size) => {
                    log!("Read {} bytes: {:?}", size, &buffer[..size]);
                }

                Err(_err) => {
                    // log!("Error ! {:?}", &err);
                }
            };
            thread::sleep(Duration::from_millis(200));
        }
    });

    let write_port = Arc::clone(&shared_port);

    let write_thread = thread::spawn(move || {
        let value = [0x1b, 0x03, 0x00, 0x00, 0x1e];
        let mut serial = write_port.lock().unwrap().try_clone().unwrap();
        loop {
            let mut input = String::new();
            io::stdin().read_line(&mut input).unwrap();
            log!("<=== your press time {}", input);

            match serial.write(&value) {
                Ok(size) => {
                    log!("write success  size {}", size);
                }
                Err(error) => {
                    log!("write err  {:?}", &error);
                }
            };
            thread::sleep(Duration::from_millis(100));
        }
    });

    if let Err(e) = read_thread.join() {
        eprintln!("Read thread panicked: {:?}", e);
    }

    if let Err(e) = write_thread.join() {
        eprintln!("Write thread panicked: {:?}", e);
    }
}

windows

image

Mac

image

The same operation is very fast in Mac, and in Windows, it is necessary to reread and call the read method after timeout to obtain data, and the write operation is also very time-consuming.

barries commented 3 months ago

I also see this issue on Windows 11 Pro, serialport-4.3.0. This makes it very slow to deal with the motor controller I have to work with on Windows. Unfortunately, I'm writing a tech eval to see if we want to transition to Rust and this is currently one of "cons" that weighs against a transition.

sirhcel commented 2 months ago

Thank you for bringing up this issue @3Q-! I've created a test case based on your example and it looks to me that this issue has been fixed recently with #79. This fix got already released with 4.4.0.

Could you please try 4.4.0 @3Q- and @barries?

sirhcel commented 2 months ago

This behavior should be fixed with 4.4.0. Please reopen if there are still issues.