38
Raspberry PiとArduinoを一緒に使う方法

ArduinoとRaspberry Piは全く異なる製品ですが、どちらも熱心なハッカーやメーカーのニーズに応えています。ArduinoをRaspberry Piに接続し、入力に反応してPython経由でRaspberry Piに出力を送信するスレーブデバイスとして使えたらどうでしょうか? 

Arduinoは本格的なコンピューターではありませんが、内蔵ADCチップによるアナログ-デジタル変換など、いくつかの点でコンピューターより優れています。ArduinoをRaspberry Piに接続するには、専用のソフトウェアが必要になります。このチュートリアルはそこから始めます。 

Raspberry PiをArduinoで使用するためのソフトウェア設定

Pythonコードを書く前に、Linux ARM 32ビット版Arduino IDEをダウンロードしてインストールする必要があります。インストールが完了したら、 Arduinoにデータを送信するために、ユーザー「pi」を適切なグループに追加する必要があります。piをグループに追加するには、ターミナルを開いて以下を入力します。 

$ sudo usermod -a -G dialout pi

 次に進む前に、Raspberry Piを再起動してください。Piを再起動したら、Arduino IDEを開き「ファイル」>「例」>「基本」>「Blink」を選択し「ツール」>「ボード」でボードを選択してください。テストではArduino Unoを使用しました。 

次に、「ツール」>「ポート」に移動し、ボードのポートが選択されていることを確認します。「スケッチ」>「アップロード」(またはメニューの矢印をクリック)をクリックして、コードをArduinoにアップロードします。数秒後、Arduino内蔵のLEDがゆっくりと点滅するはずです。これでArduinoが動作していることがわかります。 

テストが完了したら、ArduinoとPythonで通信するための特別なスケッチを書き込みます。「File > Examples > Firmata > StandardFirmata」と選択し、このスケッチをArduinoに書き込みます。書き込みが完了したら、Arduino IDEを閉じてください。pyFirmataライブラリをインストールするには、新しいターミナルを開き、以下を入力します。 

$ sudo pip3 install pyfirmata

Raspberry PiでArduinoを使ってHello Worldプロジェクトをプレイ 

ArduinoがPythonで動作するかテストするために、Arduinoの12番ピンに接続されたLEDを点灯させる簡単なスクリプトを作成します。接続については図をご覧ください。

Tom's Hardware の最高のニュースと詳細なレビューをあなたの受信箱に直接お届けします。

Raspberry PiでArduinoを使う:Arduino LEDライトの図

Arduino Uno が LED ライトに接続する様子を示す図。(画像提供: Future)

Arduinoを接続し、ターミナルに以下のコードを入力します。ttyUSB0やttyACM0などのUSBデバイスを探します。先に進む前にメモしておいてください。

$ dmesg

お好みのPython 3エディタ(IDLE、Thonny、nano、Vim)を使って新規ファイルを作成しLED_test.py という名前を付けますこのファイルにPythonコードを記述します。まず、pyFirmataライブラリから2つのクラスをインポートします。これにより、Arduinoに接続できるようになります。次に、timeライブラリからsleep関数をインポートします。 

from pyfirmata import Arduino, util
from time import sleep

次のステップは、 Raspberry PiからArduinoへの接続となる「board」というオブジェクトを作成することです。そのためには、dmesgから取得したUSBデバイス情報を使用する必要があります。今回の場合、ArduinoはttyUSB0に接続していました。 

board = Arduino('/dev/ttyUSB0')

LEDという変数は、Arduinoのピン番号を格納するために使用されます。この変数を作成するには、以下の行を追加します

led = 12

while Trueループの中に、0.2秒ごとにLEDのオン/オフを切り替えるコードを記述します。オブジェクトboardを呼び出し、ピンをデジタル値(0,1)で制御するクラスを定義し、ピンに1を書き込んでLEDを点灯させます。ピンを識別するために変数ledを使用していることに注意してください。その後、0.2秒間スリープし、その後ピンをオフして再びスリープします。 

while True:
board.digital[led].write(1) sleep(0.2) board.digital[led].write(0) sleep(0.2)

コードを保存し、エディターから実行します (IDLE 実行 > モジュール実行/Thonny 実行 > 現在のスクリプト実行)。数秒後に Arduino に接続された LED が点滅し、接続が機能していることが証明されます。

最終的な Python スクリプトは次のようになります。

from pyfirmata import Arduino, util
from time import sleep
board = Arduino('/dev/ttyUSB0')
led = 12
while True: board.digital[led].write(1) sleep(0.2) board.digital[led].write(0)
sleep(0.2)

Raspberry PiとArduinoでLEDライトを点滅させる

 では、新しいプロジェクトを作りましょう。これは点滅するLEDですが、点滅間隔はポテンショメータというアナログ電子部品で制御します。Raspberry Piでは通常、ポテンショメータはADC(アナログ-デジタル変換)ボードなしでは使えません。 

Arduinoから返される値を使って、LEDの点滅速度を制御できます。先ほど構築・テストした既存のLEDテスト回路にポテンショメータを追加します。詳細については、下の図をご覧ください。

Raspberry PiとArduinoの併用:ポテンショメータ回路図付きArduino

ポテンショメータとLEDライトに接続されたArduino Unoボード。  (画像提供:Future)

このプロジェクトのコードは、新しい空のファイルで開始し、同じ行を使用して、Arduino で使用されているピンをインポートおよび構成します。  

from pyfirmata import Arduino, util from time import sleep board = Arduino('/dev/ttyUSB0') led = 12

Arduinoからアナログ値を読み取るには、メインコードを中断せずに実行されるスレッドを作成する必要があります。スレッドを開始する前に、 itというオブジェクトを作成し、Arduinoに接続する必要があります。 

it = util.Iterator(board) it.start() board.analog[0].enable_reporting()

コードの本体はwhile Trueループで、ポテンショメータに接続されたアナログピン0の現在の値を読み取り、その値をvalueという変数に格納します。この値はPythonシェルに表示されます。 

while True: value = board.analog[0].read() print(value)

 条件付きテストが変数 valueに適用されます。値にデータがない場合、none が返され、コードがクラッシュします。そのため、if条件で値をチェックし、none の場合は 0 に変更します。  

 if value == None: value = 0

これをテストするためのもう一つの条件は、値が0.05より大きい場合、返されるアナログ値は0.0から1.0の間であるということです。値が0.05より大きい場合、LEDは点灯し、コードを一時停止してLEDのオン/オフを維持するために使用されるスリープ間隔は、によって制御されます。  

 elif value > 0.05: board.digital[led].write(1) sleep(value) board.digital[led].write(0) sleep(value) 

最後のコード行はelse条件で、値が0.05未満の場合にLEDを消灯します。コードを保存して実行してください。ポテンショメータを回してLEDが点灯するのを確認してください。最終的なPythonコードは以下のようになります。

from pyfirmata import Arduino, util from time import sleep board = Arduino('/dev/ttyUSB0') led = 12 it = util.Iterator(board) it.start() board.analog[0].enable_reporting()
while True: value = board.analog[0].read() print(value) if value == None: value = 0 elif value > 0.05: board.digital[led].write(1) sleep(value) board.digital[led].write(0) sleep(value)

この記事はもともと Linux Format Magazine 260 号に掲載されたものです