c-bata web

@c_bata_ のメモ。python多め

Raspberry PiからArduinoを制御する(シリアル通信,I2C通信)

Raspberry PiからArduinoを制御

ここはかなりつまづいた。python用のシリアル通信のパッケージをインストールしてから,pythonスクリプトArduinoに信号を送ってみたものの,Arduinoの動作がおかしくて一度挫折しましたが,解決しました。

シリアル通信

まずはArduino側のプログラムを作成。

byte val=0;
int led = 13; 

void setup() { 
        pinMode(led, OUTPUT); 
        Serial.begin(9600);
}

void loop() {
        if(Serial.available() > 0){ 

                val = Serial.read();
                Serial.print(val); //for debug

                else if(val == 'a'){   
                        digitalWrite(led,HIGH);
                        delay(1000);
                }
                else if(val == '0')
                {   
                        digitalWrite(led,LOW);
                        delay(1000);
                }
        }   
}

シリアル通信で'a'という文字を受け取ると,ArduinoのDigitalピンの13番につないでいるLEDが点灯し,'0'という文字を受け取ると光っていたLEDが消灯します。このプログラムは1バイトの文字を受け取ることが出来ます。

Arduino側のプログラムを書き込み,Raspberry PiとArduinoを接続。Pythonの対話モードを起動し,↓のように入力していくと,ArduinoのLEDは期待通りの動作をしてくれます。

$ python
>>> import serial
>>> ser = serial.Serial('/dev/ttyACM0', 9600)
>>> ser.write('a')
>>> ser.write('0')
>>> ser.close()

対話モードでシリアル通信がうまくいくことが確認できたので,ここで入力した命令をtest.pyというファイルに書き込み実行すると...点灯しない。原因がわからず,調べているとこちらのページで解決方法が載せられていました。

結果から言うとどうやら,シリアル通信の開通後1.5秒ぐらいはArduinoがブート中らしく,信号を受け取れる状態ではないらしい。 そのためtimeモジュールをインポートして,2秒ほど待つと成功しました。本当に感謝です。

# coding: utf-8

import serial
import time

ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(2)  //Arduinoのブート待ち
ser.write('a')
ser.close()


Pythonシリアル通信で文字・文字列を送受信する命令をメモ

こちらにうまくまとまっていました。

  • Serial.read() 相手機器から送られたデータを1バイト読み出し(1文字)
  • Serial.readline() 相手機器から送られたデータを一行分読み出し(改行コードまで)
  • Serial.write() データを1バイト送信(1文字)。Serial.printっていう命令もあるみたいですが違いは不明
  • Serial.println() データを一行分送信(改行コードまで)

Arduino側で文字列を受信するには,ループを使用して一文字ずつ読み込まないといけないので,少し面倒くさいです。 そのため,僕は↓のように使い分け。

  • RaspberryPiからArduinoに制御信号を送信する時は,Serial.write()で1バイトの文字をやりとり
  • ArduinoからRaspberryPiに信号を送信する時はSerial.readline()で文字列をやりとり


I2C通信

I2Cはシリアル通信がうまくいかなかった時に,やってみました。但し、結果から言うと失敗。とりあえず手順をメモします。今はシリアル通信が成功したのでI2Cは使わないと思います.

i2cソフトのインストール

参考資料 : - 誰でもできる! Raspberry Piで楽しもう (日経BPパソコンベストムック) - raspberrypi/Raspberry PiでIO制御 - Raspberry Pi and Arduino Connected Using I2C

I2C用のパッケージのインストール

$ sudo apt-get install i2c-tools

次にI2Cモジュールがロードできるか確認

$ sudo modprobe i2c-bcm2708
$ sudo modprobe i2c-dev
$ lsmod
Module    ...
i2c_dev    ...
i2c_bcm2708    ....
...
...

↑のように,i2c_devとi2c_bcm2708がlsmodで表示されれば2つのモジュールがロードされたことが確認できます。

次に再起動した後も,モジュールが自動的にロードされるように設定を変更。/etc/modulesの最終行に↓にしめす2行を追記

$ sudo vim /etc/modules
$ tail /etc/modules
i2c-bcm2708
i2c-dev

次はpiユーザーでもi2cデバイスを操作できるようにpiユーザーのサブグループにi2cグループを追加しておく。

$ sudo usermod -a -G i2c pi

i2c-bcm2708はドライバの自動ロードを禁止する「blacklist」に登録されているので,その行を修正。blacklist i2c-bcm2708の行頭に#をつけてコメントアウトする。

$ sudo vim /etc/modprobe.d/raspi-blacklist.conf
$ less /etc/modprobe.d/raspi-blacklist.conf
# blacklist spi and i2c by default ( ...

blacklist spi-bcm2708
#blacklist i2c-bcm2708

ここで一旦Raspberry Piをシャットダウンする。

$ sudo shutdown -P -h now

実際にi2c通信やってみる

ここまで終わればi2c通信が出来るかテストする

参考資料

↑のリンクの1つ目のサイトを参考に,ArduinoとRaspberry Piを接続。 ArduinoにUSBの電源をつないで,Raspberry Piを起動

$ sudo apt-get install python-smbus
$ i2cdetect -y 1

するとどこかに数字が出てくるということなのですが,なぜか出てきいませんでした。 シリアル通信だけでなくI2C通信も僕の知識ではうまくいきませんでした。 参考資料に書いてあるとおりにやったつもりなのですが,どこかで手順を間違えてしまったのかもしれません.

cuを使ったシリアル通信

cuを使ったシリアル通信は,ArduinoとRaspberryPiのシリアル通信がうまくいかず色々調べているとcuというプログラムを利用するとArduinoにうまく信号を送ることができたというものです。 これは,もうpythonでシリアル通信に成功したので必要ない情報かもしれない。

とりあえずメモ まずは,こちらを参考に↓のスケッチをArduinoに書き込む。

int incomingByte = 0;  

void setup(){
    Serial.begin(9600);
    pinMode(13,OUTPUT);
    digitalWrite(13,LOW);
}
void loop(){

    while(Serial.available()>0){
        incomingByte = Serial.read();
        if(incomingByte<(int)'1') continue;
        if(incomingByte>(int)'9') continue;
        Serial.write(incomingByte);
        incomingByte=incomingByte-(int)'0';
        while(incomingByte>0){
            digitalWrite(13,HIGH);
            delay(250);
            digitalWrite(13,LOW);
            delay(250); 
            incomingByte--; 
        }
    }
}

次に,Raspberry Piにcuというシリアル通信用のパッケージをインストール

$ sudo apt-get install cu

信号を送信するにはRaspberry piとArduinoをUSBで接続して,↓のコマンドを打ちます

$ cu -l /dev/ttyACM0 -s 9600

この状態で,数字を入力するとその回数だけLEDが光ります。 cuを終了するには"~"を入力した後に"."を入力してください。 もし終了できなかったらEnterを押してからもう一度やると良いようです。

Arduinoをはじめようキット

Arduinoをはじめようキット