pySerial在Python解释器中工作良好,但不是独立的
早上好!最近我买了一块Arduino板,在我的房间里做一种“灯光控制”。以下是我编写的固件代码:pySerial在Python解释器中工作良好,但不是独立的,python,linux,serial-port,arduino,pyserial,Python,Linux,Serial Port,Arduino,Pyserial,早上好!最近我买了一块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 &&
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脚本来执行相同的操作:
#!/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);
}
}
int控制=0;
int引脚=0;
无效设置()
{
Serial.begin(9600);
用于(引脚=0;引脚0)
{
control=Serial.read();
如果(控制=(256-13))数字写入((256控制),则为低电平;
串行打印LN(控制);
}
}
您的strace输出显示它打开串行端口读/写两次。第二次只写入chr(12),然后关闭文件。我没有足够的信息为您解决这个问题,但这可能会有帮助吗?还是你已经弄明白了?我猜这与环境有关
import os
print os.environ['PS1']
从一个不会被设置的脚本。(也许还有别的事情。)
tty将根据他们是否认为终端是交互式的而进行不同的缓冲。这应该是两种方法工作方式的唯一区别。许多应用程序决定是否设置PS1(终端提示符)。如果在您的环境中手动设置,它可能会以交互方式开始运行
另外,我会在脚本中手动调用调用pyserial flush命令。(这将是最好的方式,而不是伪装成一个交互式终端。)我认为这可能是串行端口打开和数据发送之间的竞争条件。我可能会在开放电话和写电话之间睡一觉
或者,您可能不想使用这个“串行”库,只想直接打开并写入设备,也许它做了一些有趣的事情(请参阅其他帖子中提到的双重打开)您可以在打开串行连接时再次检查Arduino是否复位吗?如果它确实重置了您发送的第一个串行字节,则引导加载程序将接收到它,而不是您的代码。然后,引导加载程序可能会假定您希望对控制器进行编程,并等待进一步的命令和/或数据 引导加载程序的确切行为取决于特定的Arduino 为了测试这一点,写一个LED 13闪烁的小草图,看看初始化Python脚本是否会影响闪烁。如果是这样,则有一个引导加载程序 为了解决这个问题,有几种可能的解决方案: 1) 确保初始化串行接口不会导致复位。 1a)在Python端执行此操作 1b)在Arduino侧进行此操作 1b硬件解决方案)断开电路板上有问题的记录道 1b软件解决方案)摆脱引导加载程序 2) 引导加载程序工作时不要发送数据
最简单的解决方案是(2)我更喜欢的解决方案是摆脱引导加载程序。然而,在这种情况下,您需要一个系统内程序员(无论如何这是一个好主意)。Did
ser.write(chr(12));睡眠时间(1);ser.write(chr(256-12))
在控制台上工作正常?是的。指示灯打开、关闭,jpnevulator显示控制器返回的数据。当我对脚本执行相同操作时,jpnevulator显示没有返回任何数据,也没有发生任何事情。我升级了pySerial,但没有结果。您可以尝试:0。print ser
是否从控制台和脚本生成相同的结果?1.将代码放入defmain():..
并使用if\uuuuu name\uuuu==“\uuuu main\uuuuu”:main()
2保护调用。在第一个ser.write()之前添加time.sleep(2)
。在每次写入()之后添加flush()。4.添加ser.close()哇,实际上在第一次写之前就把time.sleep(2)放进去了!它现在开始工作了!我不认为事情会这么简单。不过,它需要2秒或更长的睡眠时间才能工作。是的,它看起来好像打开了两次,然后写入第二个描述符。也许我可以试着用另一个版本的Python做同样的事情。我在一台没有串口的笔记本电脑上,否则我会很乐意帮你调试这个!由于脚本似乎成功地将chr(12)
写入了端口,运行它时灯是否至少亮了?他说没有,这表明有两个句柄打开到同一个串行端口可能是问题的一部分。一些串行设备驱动程序和UART处理控制字符的方式与普通的不同,因此,可能正在拦截chr(12)
,这是一个ASCII FF或formfeed字符。另一件事是串行通信可以是7位或8位,因此如果设置为7位,则很难通过通道发送chr(256-12)
,或0xF4,8位字符。可能还有其他通信设置,如每个字符的数据位数、奇偶校验和每个字符的停止位数,也会导致问题。不过,这些都不能解释interp与脚本之间的差异。我比较了脚本和解释器中的os.environ内容,它们看起来很相似。是的,当我在pdb下运行脚本时,一切都正常。我尝试使用flush,但似乎不起作用。我稍后会尝试修改PS1。是的,时间到了。睡眠(2)起作用了!事实上,它不依赖于编程语言,即使在C(使用POSIX调用)和C++(使用LIB系列)之前,我也有相同的问题,直到我添加了睡眠。
import os
print os.environ['PS1']