PAGE TOP

I2C通信の確認プログラム

I2C通信確認プログラム

ラズベリーパイとPICマイコン間でI2C通信するための電圧レベル変換モジュールを基板の上にとりつけた。
続いては、実際に通信できるか試験用プログラムを作って確認。


NゲージのレイアウトでPICマイコンを使ってポイントマシンを動作させたり信号の点灯制御を行うためのもの。
Raspberry Pi3がマスターとなって全体を制御し、実際にポイントマシンを転換するPICマイコンなどがスレーブとなる。

環境

環境としては次のようなものになる。

I2C通信確認テスト環境


マスターとなるRaspberry Pi3と電圧レベル変換モジュールがある基盤は数センチのケーブルで繋ぐが、そこから先のスレーブの基盤は2~3メートルから数メートル程度のLANケーブルで接続する。

動作確認のフェーズ

I2Cのプログラムを作るのは初めて。
他人様のHPを参考に一気呵成に環境を作ってプログラムをコピペして動けば、それに越したことはないが、世の中そんなに甘くない。
今回のようにマスター側のプログラム、スレーブ側のプログラム、マスターとスレーブをつなぐ電圧レベル変換モジュールなどが絡んでくると切り分けが大変そう。

ということで、少しずつ動作確認を行ってきている。
今一度振り返ると。

Raspberry Pi3の設定

Raspberry Pi3でI2C通信を使用できるようにするためには設定を行っておく必要がある。
これは、ラズベリーパイ3・I2C通信の準備のような手順で実施。

電圧レベル変換モジュールと疎通確認

Raspberry Pi3側が3.3V、PICマイコン側が3.3V、5V混在という予定なので、中間に電圧レベル変換モジュールが必要になる。
そのために、電圧レベル変換モジュールを取り付けた基板を作った。

その際に、スレーブとなるPICマイコンでI2C通信を担うMSSPモジュールを有効にする設定のみを行ったプログラムを作成した。
これは単にPICマイコン側のクロックの設定が正しいか、MSSPモジュールが有効になっているかの確認のみなので、実際に実行する部分としてはLEDの点滅のみの簡単なもの。

マスター側のRaspberry Pi3で「i2cdetect」コマンドを実行し、スレーブのアドレスが表示されれば電圧レベル変換モジュールを経由してPICマイコンも所定のクロックでI2Cスレーブとして動作していることの疎通確認ができるというものだった。

実際にスレーブ側からデータを送信し、マスター側で受け取る

今回の確認はここ。

Raspberry Pi用のGPIOインターフェイスライブラリ「wiringPi」の使い方も含めた検証なので、単純に1バイトのデータの送受信のみ。

試験にあたっては、スレーブ側のPICマイコンはブレッドボード上に置いたが、実際に使用する電圧レベル変換モジュールを取り付けた基板とは2メートルほどのLANケーブルで接続し、実環境に近づけた。

 

I2C通信プログラムの確認中 よく他人様のHPでみかけるような奇麗に整理された環境とは程遠いゴチャゴチャの環境。


ちなみに、Raspberry Pi3は透明のプラケースに入れ、他の基盤の裏面にはプラダンなどの絶縁物のシートをネジ止めして絶縁しているので、テキトーな位置にポっと置いてもショートすることはない・・ハズ。
でも、念のため畳の上でテスト。

通信テストプログラム

当初、スレーブ側から送信した1バイトのデータをマスター側で表示させるというプログラムを作成して動作の検証を行っていた。
その確認ができれば、次のフェーズでマスター側からデータを送信し、スレーブ側で受信できるか、という形に改修しようとしていた。
しかし、意外に簡単に改修できたので、ソースプログラムはこのページの末尾に記載しなおします。

 

トラブルの切り分け

前項のプログラムは最終的に動作確認ができたものであるが、実際にはすんなり動かなかった。

さて、マスター側のプログラムなのか、スレーブ側のプログラムなのか、はたまたハード上の問題なのか?

マスター側プログラムの切り分け

他人様のHPを拝見すると温度計や加速度計のサンプルプログラムではwiringPiの「wiringPiI2CReadReg8()」などで相手方のレジストリを直に取得する?ような感じ。

しかし、アタイはスレーブ側から送られた値を「wiringPiI2CRead()」という関数で取得したい。
なので、試しに温度計のモジュールを購入して実際に接続してみて・・という方法では切り分けられない。

プログラムを動作させたところ、何がしかの値は取得できているようだったが、スレーブが送信したはずの値ではなかった。

現時点で確認できることといえば・・
存在しないスレーブのアドレスを指定するとwiringPiI2CSetup()がエラーを戻すか
動作中にスレーブの電源を切ったら、値の表示が止まるか

確認したところ、存在しないアドレスだとエラーになるし、動作中にスレーブの電源を切るとwiringPiI2CRead()のエラー値(0xff)を表示するようになった。

この時点で、マスター側プログラムは正しく動作しているものと思えた。

 

スレーブ側プログラムの切り分け

MPLAB X IDEとPickit3を使えばデバッグも可能であるが、割り込みルーチンが絡んでくるとどうもうまくデバッグすることができない。

実環境で最低限どこまで進んでいるのかを確認するのにLEDを使用した。

最初にLEDを点灯させておき、
RC2 = 0; // 確認用LED消灯
というのを書く位置を変えながら動作を確認してみる。

・・最初にLEDを消灯させておき、指定の位置にきたらLEDを点灯・・
そんな方法はポートの入出力の設定がちゃんとできていないとLEDは点灯しないし、LEDの極性を間違えて接続していても点灯しないのでお勧めできません(^^;

 

スレーブ側モジュールを変更してみる

スレーブ側のモジュールを他のものに変更してみる。
しかし、前述のように今回は温度計や加速度計のモジュールは使用できない。

となると用意できるのは「Arduino Uno」

Arduino Unoも追加して確認


参考にさせてもらったのは「Arduino同士でI2C通信する方法」という記事。

それによれば、

#include <Wire.h>

byte b=0;

void setup() {
    Wire.begin(8);// Slave ID #8
    Wire.onRequest(requestEvent);
}

void loop() {
}

void requestEvent() {
    Wire.write(b++);
}

という記述だけで、マスターから呼び出される都度1ずつインクリメントした値を返すプログラム。

スレーブのアドレスを自分の環境に合わせて変更してテスト環境に組み込んで実行したら、無事マスター側に値が表示された。

つまり、PICマイコン側のプログラムに問題があることが分かった。

実行結果

結局PICマイコン側の割り込みプログラムのSSPSTATbits.R_Wの判定等に問題点があることが判明し、前述のとおりのソースプログラムにすることで動作が確認できた。

I2C通信確認中のコンソール


次の確認項目は、マスター側からデータを送信し、スレーブ側で受信できるか。

 

=追記=

意外にマスター側から送信したデータをスレーブ側で受信するように改修するもの簡単にできたので、ソースプログラムを等をここに記載しときます。

通信テストプログラム改修版

マスター側から1バイトのデータを送信、スレーブ側でその値を1インクリメントしてマスター側に戻す。
マスター側はその値をコンソールに表示し、さらに1インクリメントしてスレーブ側に送信する。
という繰り返し。

マスター

マスター側はRaspberry Pi3。
プログラムはC言語でgccでコンパイル。

Raspberry Pi用のGPIOインターフェイスライブラリ「wiringPi」を使用するので事前にインストールしておく。
ちなみにアタイはトラブルがありながらもインストール完了

i2ctest.c

コンパイルと実行はソースプログラムのあるディレクトリで次のコマンドを実行。

//コンパイル
gcc -o i2ctest i2ctest.c -lwiringPi

//実行
./i2ctest

 

スレーブ側

スレーブ側はPIC16F886。
プログラムはC言語でxc8でコンパイル。

このプログラムはあくまでRaspberry PiとPICマイコンが電圧レベル変換モジュールを介して通信ができることを確認するための簡易に作成した物です。
実際に使用するアプリを作るときにはSSPSTATなどを詳細に判定して処理を振り分けるなどの見直しが必要です。


SSPSTAT、SSPCON、SSPIFなどのレジスタはPICマイコンによってはSSP1STAT、SSP1CON、SSP1IFなどと異なっている場合があります。

使用するPICマイコンのデータシートを見て確認する必要があります。

実行結果は次のような感じ。

I2C通信確認中のコンソール(その2)




趣味の部屋 スマホ/タブレットサイト 趣味の部屋 PCサイト