13

早上好!最近我买了一块 Arduino 板来在我的房间里做某种“灯光控制”。这是我写的固件代码:

int control = 0;
int pin = 0;

void setup()
{
  Serial.begin(9600);
  for(pin = 0; pin <= 13; pin++) pinMode(pin, OUTPUT);
}

void loop()
{
  control = Serial.read();
  if (control > 0 && control <= 13) digitalWrite(control, HIGH);
  if (control < 256 && control >= (256-13)) digitalWrite((256-control), LOW);
}

之后,我使用 Python 解释器中的 pySerial 来控制引脚,一切正常。这是一段解释器输出:

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyUSB0', 9600)
>>> ser.write(chr(12))
>>> # The light turned on here
... 
>>> ser.write(chr(256-12))
>>> # The light turned off here
...

然后我决定编写一个简单的 Python 脚本来做同样的事情:

#!/usr/bin/env python

import serial
import time

ser = serial.Serial('/dev/ttyUSB0', 9600)

ser.write(chr(12))
time.sleep(1)
ser.write(chr(256-12))

但它根本不起作用!Arduino 显示在我启动脚本期间收到了一些东西,但没有任何反应。这是脚本的一段 strace 输出:

open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_START or TCSETS, {B9600 -opost -isig -icanon -echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B9600 -opost -isig -icanon -echo ...}) = 0
write(4, "\f", 1)                       = 1
close(4)                                = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f45cf4c88f0}, {0x4d9820, [], SA_RESTORER, 0x7f45cf4c88f0}, 8) = 0
exit_group(0)                           = ?

看起来一切都应该没问题,所以我不知道问题出在哪里。我会很感激任何帮助,非常感谢提前!

PS 当我在 PDB 下运行程序时,一切正常。一只海森堡。

更新:我让控制器将它收到的数据发回给我,当我运行脚本时它似乎没有收到任何东西,但是当我从解释器发送数据时它收到了所有东西。固件的代码现在如下所示:

int control = 0;
int pin = 0;

void setup()
{
  Serial.begin(9600);
  for(pin = 0; pin <= 13; pin++) pinMode(pin, OUTPUT);
}

void loop()
{
  if (Serial.available() > 0)
  {
    control = Serial.read();
    if (control <= 13) digitalWrite(control, HIGH);
    if (control < 256 && control >= (256-13)) digitalWrite((256-control), LOW);
    Serial.println(control);
  }
}
4

4 回答 4

9

我认为这可能是串行端口打开和数据发送之间的竞争条件。我可能会在 open 和 write 调用之间睡一觉。

或者,您可能希望直接打开并直接写入设备,而不是使用这个库“串行”,也许它正在做一些有趣的事情(参见其他帖子中提到的双打开)

于 2010-11-22T05:03:37.327 回答
1

My guess is it has something to with the environment.

import os
print os.environ['PS1']

From a script that will not be set. (And maybe something else too.)

tty's will buffer differently depending on whether or not they think the terminal is interactive. That should be the only difference between the way your two methods work. A lot applications decide this on whether or not PS1 (your terminal prompt) is set. If you set this in you environment manually it may start behaving the same way as it does interactively.

Also, I would call the call the pyserial flush command manually in your script. (And this would be the preferred way to do it. Instead of masquerading as an interactive terminal.)

于 2010-11-21T00:09:46.370 回答
0

当您打开串行连接时,您能否再次检查 Arduino 是否重置?如果它确实重置了您发送的第一个串行字节,引导加载程序将接收到,而不是您的代码。然后,引导加载程序可能会假设您想要对控制器进行编程并等待进一步的命令和/或数据。

引导加载程序的确切行为取决于您的特定 Arduino。

为了对此进行测试,请编写一个闪烁 LED 13 的小草图,并查看初始化 Python 脚本是否会影响闪烁。如果是这样,则有一个引导加载程序。

为了解决这个问题,有几种可能的解决方案:

1)确保没有初始化串口引起的复位。1a)在 Python 端执行此操作 1b)在 Arduino 端执行此操作 1b 硬件解决方案)断开板上有问题的痕迹 1b 软件解决方案)摆脱引导加载程序

2) 在引导加载程序工作时不要发送数据。

最简单的解决方案是(2)我更喜欢的解决方案是摆脱引导加载程序。但是,在这种情况下,您需要一个系统内程序员(无论如何这是个好主意)。

于 2013-05-28T20:54:05.127 回答
0

您的 strace 输出显示它打开串行端口读/写两次。第二次只写入 chr(12),然后关闭文件。我没有足够的信息来为您解决问题,但也许这有帮助?还是你已经弄清楚了?

于 2010-11-21T00:02:10.017 回答