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

おそらく、シリアルポートが開いてからデータが送信されるまでの競合状態だと思います。おそらく、オープン呼び出しと書き込み呼び出しの間にスリープ状態を維持します。

あるいは、このライブラリ「シリアル」を使用する代わりに、単に開いてデバイスに直接書き込むこともできます。おそらく、何か面白いことをしています(他の投稿で言及されているダブルオープンを参照してください)。

于 2010-11-22T05:03:37.327 に答える
1

私の推測では、それは環境と関係があります。

import os
print os.environ['PS1']

設定されないスクリプトから。(そして多分何か他のものも。)

ttyは、端末がインタラクティブであると考えるかどうかによって、バッファリングが異なります。これが、2つの方法の動作の唯一の違いです。多くのアプリケーションは、PS1(ターミナルプロンプト)が設定されているかどうかでこれを決定します。これを環境に手動で設定すると、インタラクティブと同じように動作し始める場合があります。

また、スクリプトでpyserialflushコマンドを手動で呼び出します。(そして、これはそれを行うための好ましい方法です。インタラクティブな端末になりすますのではなく。)

于 2010-11-21T00:09:46.370 に答える
0

strace出力は、シリアルポートの読み取り/書き込みを2回開くことを示しています。2回目は、chr(12)のみを書き込んでから、ファイルを閉じます。問題を解決するのに十分な情報がありませんが、おそらくこれは役に立ちますか?またはあなたはすでにそれを理解しましたか?

于 2010-11-21T00:02:10.017 に答える
0

シリアル接続を開いたときにArduinoがリセットされるかどうかを再確認できますか?リセットされた場合、送信した最初のシリアルバイトは、コードではなくブートローダーによって受信されます。ブートローダーは、コントローラーをプログラムし、さらなるコマンドやデータを待つことを想定する場合があります。

ブートローダーの正確な動作は、特定のArduinoによって異なります。

これをテストするには、LED 13を点滅させる小さなスケッチを作成し、Pythonスクリプトの初期化が点滅に影響するかどうかを確認します。もしそうなら、ブートローダーがあります。

これを修正するために、いくつかの可能な解決策があります。

1)シリアルインターフェースの初期化によるリセットがないことを確認します。1a)Python側でこれを行う1b)Arduino側でこれを行う1bハードウェアソリューション)ボード上の問題のあるトレースを切断する1bソフトウェアソリューション)ブートローダーを取り除く

2)ブートローダーが作業を行っている間はデータを送信しないでください。

最も簡単な解決策は(2)私の好みの解決策はブートローダーを取り除くことです。ただし、この場合、インシステムプログラマーが必要です(とにかくこれは良い考えです)。

于 2013-05-28T20:54:05.127 に答える