簡體   English   中英

在 Arduino UNO 中讀取沒有 IDE 的 USB 數據

[英]Read USB data without IDE in Arduino UNO

我有一個 Arduino UNO。 我編寫了一個腳本來控制連接到 Arduino 上 PIN 2、3、4 的燈。 可以使用我的筆記本電腦關閉或打開燈:

  • 0 關閉所有 LED
  • 1 打開引腳 1 上的 LED
  • 2 打開引腳 2 上的 LED
  • 3 打開引腳 1 和 2 上的 LED
  • 4 打開引腳 3 上的 LED
  • 5 打開引腳 1 和 3 上的 LED
  • 6 打開引腳 2 和 3 上的 LED
  • 7 打開所有 LED。

我實際上只對從我的筆記本電腦發送數據並相應地閃爍燈感興趣。

這是我的程序:

# pragma GCC optimize ("Ofast")

# define LED1 2
# define LED2 3
# define LED3 4

char buf[4] ;
unsigned char inp, len ;

void setup() {
    pinMode(LED1, OUTPUT) ;
    pinMode(LED2, OUTPUT) ;
    pinMode(LED3, OUTPUT) ;

    Serial.begin(115200) ;
    Serial.setTimeout(1) ;
}

void loop() {
    if (Serial.available() > 0) {
        len = Serial.readBytes(buf, 3) ;
    
        if (len) {
            buf[3] = '\0' ;
            inp = atoi(buf) ;
    
            // Illuminate LEDs
            digitalWrite(LED1, 1 & inp ? HIGH : LOW) ;
            digitalWrite(LED2, 2 & inp ? HIGH : LOW) ;
            digitalWrite(LED3, 4 & inp ? HIGH : LOW) ;
        }
    }
}

當我打開 IDE 的串行監視器並編寫printf 1 > /dev/ttyUSB0時,它工作正常。

但是當我關閉串行監視器和printf 1 > /dev/ttyUSB0時,它不起作用,我唯一得到的是閃爍的板載 LED。

所以每次我需要點亮一個 LED 時,我必須確保 IDE 是打開的。

有沒有辦法在不打開 IDE 的情況下從任何 Linux 計算機寫入 Arduino 串行端口?

好的,所以問題是 arduino 有 Serial.read() 代碼。 除非我打開 Arduino IDE 的串行監視器,否則我發送的數據將失敗。 換句話說,如果我想創建一個熱插拔設備,我的筆記本電腦會在循環中搜索並在插入時向其寫入數據,這是不可能的。

現在要解決這個問題,我需要看看 IDE 的串行監視器做了什么,它設置波特率,並在所選端口上打開文件描述符 3。

所以要解決熱插拔問題,我首先需要先設置波特率和匹配標志。 然后我需要使用 fcntl 文件描述符 3 打開文件,就像 IDE 的串行監視器一樣。

由於我在 Ruby 中寫入發送字節,因此我有機會編寫 C Ruby。 我使用以下代碼設置波特率:

VALUE setBaudRate(volatile VALUE obj, volatile VALUE dev, volatile VALUE speed) {
    char *device = StringValuePtr(dev) ;
    unsigned int spd = NUM2UINT(speed) ;

    int serial_port = open(device, O_RDWR) ;
    struct termios tty ;

    char status = tcgetattr(serial_port, &tty) ;

    // IDE sets these flags
    // speed 57600 baud; line = 0;
    // min = 0; time = 0;
    // -brkint -icrnl -imaxbel
    // -opost
    // -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

    if(status != 0) return Qnil ;
    tty.c_cflag &= ~CSIZE ;
    tty.c_cflag |= CS8 ;
    tty.c_cflag |= CREAD | CLOCAL ;
    tty.c_oflag &= ~OPOST ;

    tty.c_lflag &= ~ECHO ;
    tty.c_lflag &= ~ECHOCTL ;
    tty.c_lflag &= ~ECHOK ;
    tty.c_lflag &= ~ECHOE ;
    tty.c_lflag &= ~ECHOKE ;
    tty.c_lflag &= ~ISIG ;
    tty.c_lflag &= ~ICRNL ;
    tty.c_lflag &= ~IEXTEN ;
    tty.c_lflag &= ~ICANON ;

    tty.c_cc[VTIME] = 0 ;
    tty.c_cc[VMIN] = 0 ;

    cfsetispeed(&tty, spd) ;
    cfsetospeed(&tty, spd) ;
    status = tcsetattr(serial_port, TCSANOW, &tty) ;

    if (status == 0) return Qtrue ;
    else return Qfalse ;
}

如果您正在編寫 C,您只需將 VALUE function 名稱替換為您想要的任何名稱。 並在失敗時返回任何你喜歡的東西,它可以是 0 表示成功,1 和 2 表示失敗。

現在,確保波特率與 arduino 完美匹配。 在我的 Ruby C 擴展中,我實際上是從 Ruby volatile VALUE speed獲取波特率。 然后它設置速度。 純 C 實現不會有太大不同。

但是,在 BASH 中,您可以只使用stty

sudo stty -F /dev/ttyUSB0 -cread -clocal -isig -iexten -echo -echoe -echok -echoctl -echoe -brkint -icrnl -imaxbel -opost -icanon min 0 time 0 57600

無論如何,要寫入文件,您需要以讀寫模式打開文件。 Ruby 規定,我附上代碼以防它對某人有幫助:

require 'fcntl'
device = '/dev/ttyUSB0'

fd = IO.sysopen(device, Fcntl::O_RDWR | Fcntl::O_EXCL)
file = IO.open(fd)
file.syswrite("Hello world!")
file.close

在 BASH 中,您可以使用以下命令:

exec 3<> /dev/ttyUSB0

現在,如果您不想硬編碼 /dev/ttyUSB0,則需要從 arduino 發送一些字節,並在設置與 arduino 匹配的正確波特率后讀取。

通過這種方式,我們可以在 arduino 中讀取和寫入值!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM