SPIはクロック(SCK)と出力信号(MOSI : Master Out Slave In)と入力信号(MISO : Master In Slave Out)の3本で双方向通信を行う機能です。UART / RS-232C(調歩同期式シリアル通信)と並んで、シンプルな通信方式で、マイコン間の通信でよく用いられます。UARTはGNDを除くと、TxDとRxDの2本の信号線があれば通信できますが、あらかじめ通信速度を決めておいて、双方の速度を一致させていなければなりません。SPIではGND以外では、SCK、MOSI、MISOの3本で通信するクロック同期式シリアル通信です。通信速度はマスターとなる側がクロックを送出し、スレーブ側はそのクロックに同期して送受信を行います。
UARTもSPIもRaspberry Piは標準でサポートされていますが、事前の設定が必要です。Raspberry PiでUARTを使った通信はこちらで紹介しています。この項ではSPIを使用します。題材は2年前に作ったNTP時計です。Raspberry PiからNTP時計へは表示情報を送信するだけで、受信は行いません。Raspberry Piがマスターになるので、SCKとMOSIだけ使用し、MISOは配線していません。
piでログインしたら、rootになります。
pi@raspberrypi:~$ sudo su
modulesの最後にspidevを追加します。
spidev
raspi-blacklist.confのblacklist spi-bcm2708の行をコメントアウト(先頭に#を記述)します。
#blacklist spi-bcm2708
再起動します。
root@raspberrypi:/home/pi# reboot
piでログインしたら、spidevが有効になっているか確認します。
pi@raspberrypi:~/develop/spi$ ls -la /dev/spidev*
crw------- 1 root root 153, 0 Jan 1 1970 /dev/spidev0.0
crw------- 1 root root 153, 1 Jan 1 1970 /dev/spidev0.1
root以外のユーザーでもSPIが使用できるように、読み書き権限を付与します。
pi@raspberrypi:~/develop/spi$ sudo chmod 666 /dev/spidev0.0 pi@raspberrypi:~/develop/spi$ ls -la /dev/spidev*
crw-rw-rw- 1 root root 153, 0 Jan 1 1970 /dev/spidev0.0
crw------- 1 root root 153, 1 Jan 1 1970 /dev/spidev0.1
NTP時計にRaspberry Piを接続します。
セルフパワーのUSBハブから、Raspberry Piと時計本体の電源を取ります。
SCKとMOSIを結線します。入力はしないのでMISOは接続しません。
信号を送信してみます。
通信プロトコルは、拙作NTP時計のページでも解説しています。表示する数字の桁位置と文字を1バイトのデータで送信します。
上の図でCKがSCK、DOがMOSIに対応します。
表示する桁位置と値を1バイトのデータとして送信します。
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
内容 | 桁位置 | 数字 |
0 | 秒の1の位 |
1 | 秒の10の位 |
2 | 分の1の位 |
3 | 分の10の位 |
4 | 時の1の位 |
5 | 時の10の位 |
6 | 日の1の位 |
7 | 日の10の位 |
8 | 月の1の位 |
9 | 月の10の位 |
10 | 年の1の位 |
11 | 年の10の位 |
12 | 年の100の位 |
13 | 年の1000の位 |
動作確認ができましたので、rc.localにchmod 666 /dev/spidev0.0を記述しておきます。
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi chmod 666 /dev/spidev0.0 exit 0
現在時刻を表示するようにプログラムを変更しました。
実行する前に、環境変数TZを設定しておく必要があります。
$ export TZ=JST-9 $ ./spiclock
JJYを利用する一般の電波時計は、周囲の建物で電波が遮られたり、屋内では電波が弱くなったりして、うまく捕らえられないことがあります。さらに、液晶表示の時計なら良いのですが、LED表示では、ダイナミック点灯により発生するノイズのために、JJYの電波を受信することができません。そこで、無線LANを使用し、NTPサーバから時刻を取得するWiFi電波時計にします。
USB接続のWiFiアダプタを使用します。既に無線LANのアクセスポイントが動作していることを前提とします。
USB WiFiアダプタの設定方法は、検索するといろいろなサイトでwpa_supplicant.confを編集する方法が紹介されていたりしますが、私はうまく設定できなかったヘタレなので、X Windowを起動して、GUIのWiFi Configで設定しました。
コンソールからX Windowを起動するには、startxコマンドを実行します。WiFi Configをダブルクリックして、scanボタンを押し、アクセスポイントに接続します。接続を開始してから完了するまでに、10~30秒くらいかかります。