当前位置: 首页 > 知识库问答 >
问题:

在Arduino UNO中读取无IDE的USB数据

广乐邦
2023-03-14

我有一辆Arduino UNO。我写了一个脚本来控制连接到Arduino上引脚2、3、4的灯光。使用我的笔记本电脑可以关闭或打开这些灯:

  • 0关闭所有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时,它工作正常

但是当我关闭串行监视器,并且

所以每次我需要点亮LED时,我必须确保IDE是打开的。

有没有一种方法可以在不打开IDE的情况下从任何Linux计算机写入Arduino串行端口?

共有1个答案

袁开宇
2023-03-14

问题是arduino有序列号。read()代码。除非我打开Arduino IDE的串行监视器,否则我发送的数据将失败。换句话说,如果我想创建一个可热插拔的设备,我的笔记本电脑在循环中搜索该设备,并在插入时向其写入数据,这是不可能的。

现在要解决这个问题,我需要看看IDE的串行监视器做什么,它设置波特率,并在所选端口上打开文件描述符3。

所以为了解决热插拔问题,我首先需要先设置波特率和匹配标志。然后我需要像IDE的串行监视器一样使用fcntl文件描述符3打开文件。

因为我是用Ruby编写发送字节的,所以我有机会编写C Ruby。我用以下html" target="_blank">代码设置波特率:

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函数名称替换为您想要的任何名称。失败时返回您喜欢的任何内容,成功时可以为0,失败时可以为1和2。

现在,确保baudrate与arduino完美匹配。在我的Ruby C扩展中,我实际上是从Ruby挥发性VALUE速度中获取baudrate。然后它设置速度。纯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的值!

 类似资料:
  • 我有一个包含以下代码的Eclipse项目: 它不会产生任何错误,并且可以正常工作,但是当我在IntelliJ中重用相同的代码时,它会产生以下错误: 错误:类org.json.simple.JSONObject中的java: constructor JSONObject不能应用于给定的类型;必需:未找到参数:java.lang.String原因:实际参数列表和形式参数列表长度不同 错误:java:找

  • 我想在Android11上读一个OTG USB,我可以在Android9上列出这样的文件: 问题是为什么我在Android 11上可以读取外存,却不能读取OTG USB?我想要能够在Android11上读取USB OTG。

  • 我正在尝试从连接到主机模式下的Android手机的USB设备中获取一些数据。我可以发送数据到它,但读取失败。 我一直从方法获得,它指示某种错误,它总是超时。也许问题来自于连接配置,我试了几次(读作:试错),没有一次奏效,令人惊讶的是,我不需要任何配置来发送数据到设备。 编辑 还必须注意的是,我使用的电缆是micro-USB到micro-USB的,它只能以一种方式工作,即只有当插头A连接到电话和插头

  • 问题内容: 如何使用Selenium IDE获取给定表的行数? 当我右键单击表格时,我只能声明/验证以下内容: 标题 值 文本 表 元素存在 目标是 问题答案: 您要使用命令。这需要可存储在IDE内两个参数和字段,其中以下参数分别是: xpath :要评估的xpath表达式 变量名 这是表格的示例: 其中,在上面是你的div数。 提示:在Selenium IDE打开的情况下右键单击表即可快速获取路