pySerial在Python解释器中工作正常,但不是独立的

早上好! 最近我买了一块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); } } 

我想这可能是串口打开和数据发送之间的竞争状态。 我可能会坚持在打开和写入电话之间的睡眠。

或者,不要使用这个“串行”库,你可能想直接打开并直接写入设备,也许它做了一些有趣的事情(请参阅其他文章中提到的双开放)

我的猜测是这与环境有关。

 import os print os.environ['PS1'] 

从一个不会被设置的脚本。 (也许还有其他的东西。)

根据他们是否认为终端是交互式的,tty's会有不同的缓冲区。 这应该是你的两种方法工作的唯一区别。 许多应用程序决定是否设置PS1(您的终端提示符)。 如果你手动设置在你的环境中,它可能会以与交互方式相同的方式开始。

另外,我会在脚本中手动调用pyserial flush命令。 (这将是最好的办法,而不是伪装成一个交互式终端。)

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

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

引导程序的确切行为取决于您的具体Arduino。

为了测试这个写一个闪烁LED 13的小草图,看看是否初始化你的Python脚本会影响闪烁。 如果是的话就有一个bootloader。

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

1)确保没有初始化串行接口引起的复位。 1a)在Python端做这件事1b)在Arduino端1b硬件解决方案上做这件事)断开板1b软件解决方案中的违规迹线)摆脱引导程序

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

最简单的解决方案是(2)我最喜欢的解决方案是摆脱bootloader。 然而在这种情况下,你需要一个系统程序员(无论如何这是一个好主意)。