シリアルポート

Raspberry Piのシリアルポートはデフォルトではシリアルコンソール用として使用されていることを、以前にUSBシリアル変換モジュールを接続して確認した。今回はその続き。

システムが使用しているシリアルポートをユーザが使用する為には、二つの設定ファイルを修正する必要がある。一つはシステムの起動スクリプトである /etc/inittab、もう一つはコンソールデバイスの設定ファイルである /boot/cmdline.txt だ。

/etc/inittab は最後の行の

T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

をコメントアウト

/boot/cmdline.txt は

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext$

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

のように変更する。

両方のファイルを修正して保存したら、システムを再起動すればシリアルコンソールが無効になるはずなのだが、起動時の

Uncompressing Linux… done, booting the kernel.

というメッセージだけはシリアルポートに出力されてしまう。このメッセージはカーネルが出力しているらしいので、設定を変えただけでは禁止する事ができないようだ。Raspberry Piにシリアル機器を接続した場合、これがゴミデータとなってしまう可能性があるので、注意が必要。

シリアルポートをPythonで扱うためにはモジュールのインストールも必要なので

sudo apt-get install python-serial

でインストールしておく。これでRaspberry Piのシリアルポートを扱う準備は整った。

まずは以前作ったTCPソケット通信のプログラムを修正して、TCPとシリアルポート間で通信を行うプログラムを作ってみた。ソースは以下の通り。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import socket
import select
import Queue
import sys
import serial

def socketio(sock, comm):
    ilst = [sock, comm]
    olst = []
    ique = Queue.Queue() 
    oque = Queue.Queue() 
    connect = False
    while True:
        # socket i/o
        rlst, wlst, xlst = select.select(ilst, olst, [], 0)
        for si in rlst:
            # accept?
            if si == sock:
                if not connect:
                    # connect
                    conn, address = si.accept()
                    print 'connect', address
                    connect = True
                    ilst.append(conn)
                    olst.append(conn)
                else:
                    # discard
                    conn, address = si.accept()
                    conn.shutdown(socket.SHUT_RDWR)
                    conn.close
            elif si == comm:
                data = comm.read()
                oque.put(data)
            else:
            # recv?
                data = si.recv(1024)
                if data:
                    ique.put(data)
                else:
                    # disconnect
                    print 'disconnect'
                    connect = False
                    ilst.remove(si)
                    olst.remove(si)
                    si.close
                    with ique.mutex:
                        ique.queue.clear()
                    with oque.mutex:
                        oque.queue.clear()
        for so in wlst:
            if not oque.empty():
                # send
                data = oque.get_nowait()
                so.send(data)
        # Serial
        if not ique.empty():
            data = ique.get_nowait()
            comm.write(data)
                        
def start(host, port, bps):
    try:
        comm = serial.Serial('/dev/ttyAMA0', bps)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind((host, port))
        sock.listen(1)
        socketio(sock, comm)
    except KeyboardInterrupt:
        print '\nbreak'
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()

if __name__ == "__main__":
    start('', 5555, 115200)

このプログラムを起動して、Raspberry Piと同一のネットワークに接続されているPCから、Raspberry PiのIPアドレスのポート5555に対してtelnet接続を行う。接続が確立されたら、telnetクライアントからネットワーク経由でRaspberry Piに送られた文字がシリアルポートに出力され、逆にシリアルポートに入力された文字がtelnetクライアントに表示されるはずだ。

これで何ができるかと言うと、Raspberry Piのシリアルポートに接続されたデバイスを、遠隔地からネットワーク経由で使う事ができる。制御線を使用するようなデバイスには対応できないが、単純な無手順の伝送でなら使い道はあると思う。

この話はまだ続くのだが、長くなるので今回はここまで。後半は近日中に。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中