シリアルポートに接続されたいくつかのデバイスがあります。実際にはArduino
温度センサーに基づいています。
私はシリアルポートに接続し、デバイスにコマンドを送信し、応答を受け取り、印刷して終了するstdout
スクリプトを作成したいと思います。
これを行う正しい方法は何ですか?
通常、ローカルプログラムにアクセスするときにその出力をリダイレクトするだけで十分です。たとえば、CPU
温度を読み取る方法は次のとおりです。
datetime=$(date +%Y%m%d%H%M%S)
cputemp=$(sensors atk0110-acpi-0 | sed "s/CPU Temperature:[^0-9]*\([0-9\.]\+\).*/\1/;tx;d;:x")
echo "$datetime\t$cputemp"
残念ながら、$()
シリアル通信では、そうでない明示的なプログラム終了に依存します。シリアルサーバーは常にオンラインであり、明示的な「セッション」はありません。
もちろん改行文字を確認できます。しかし、これが正しいことでしょうか?すべての応答の後に送信さArduino
れるようにプログラムを作成する必要がありますかCtrl-Z
?
ベストアンサー1
あなたが言ったように、シリアルポートはファイルの終わりを読み取ることができません。 (Ctrl-ZはMicrosoftのものです)。したがって、通常は必要な文字数が得られるまで、または区切り文字(データの終わりを表す改行文字など)が見つかるまで読みます。
たとえば、出力が入力に再接続されるUSBシリアルポートがあるため、デバイスへのすべての書き込みが直接返されます。次のスクリプトは、デバイスから送信されたコンテンツを取得できます。
#!/bin/bash
tty=/dev/ttyUSB0
exec 4<$tty 5>$tty
stty -F $tty 9600 -echo
echo abcdef >&5
read reply <&4
echo "reply is $reply"
スクリプトはシリアルデバイスを入力用のファイルディスクリプタ4、出力用のファイルディスクリプタ5に接続し、速度を設定し、ttyが取得するエコーを停止し、デバイスに「abcdef」と改行文字を書き込みます。各文字は即座に再送信されますが、カーネルドライバは一部の入力をバッファリングするため、書き込み前にデバイスから読み出しを開始する必要はありません。デフォルトでは、改行文字が表示されている場合は読み取りが終了し、それを変数に保存してreply
標準出力に表示します。このスクリプトをv=$()
型の使用に入れることができます。
シリアルデバイスデータが改行文字で終わらない場合は、bash読み取りに別の区切り文字を指定できます-d
。または、応答長が一定の場合は、指定された長さを使用できます-n
。バイナリデータがある場合は、raw
sttyコマンドに追加して入力の特別な処理を停止する必要があります。