オープンソース活用事例
近年、Raspberry PiやArduinoといった市販ハードウェアと、それらのハードウェア上で動作するオープンソースソフトウェアを利用することで、安価にシステム開発を行う事例が増えてきています。
今回は、Raspberry PiやArduinoを使い「より安く、スピーディな開発」について、実験用のシステムを通して紹介致します。
Raspberry Pi 3 Model B
Genuino101
製作するシステムの構成
今回は制御対象の情報を収集するデバイス(Genuino101)と、そのデバイスからの情報を蓄積、解析するコンピュータボード(Raspberry Pi 3 Model B。以下、Raspberry Pi)で構成し、具体的には左図に示すようなシステムとします。
Genuino101には制御機器をイメージした基板を接続し、Bluetooth経由で制御機器の動作状態をRaspberry Piに送ります。Raspberry Piはその情報から制御機器の状態を把握し、モニター画面上で管理者に動作状況を伝えます。今回の制御対象はリレーです。
リレーなどの機械的な動作をする部品には故障がつきものです。また半導体部品と比べると製品寿命も短いので、長期間使用する為には寿命が尽きる前に交換するなどのメンテナンスが必要になります。そこで、動作状況を監視して部品がなんらかの原因で故障したことを検知したり、故障する前に予測できれば便利です。
今回は制御対象が一つですが、制御対象を増やし色々なデータを取れる様に拡張する事が出来ます。また、オープンソースとして公開されているソフトウェアを利用した故障検知、予測システムを開発する事も可能です。
制御基板製作
まずは制御基板を製作します。回路図と部品表は、次の通りです。
部品表
| 番号 | 個数 | 部品番号 | 型番 |
|---|---|---|---|
| 1 | 1 | D1 | D1NS4-5060 |
| 2 | 1 | CN1 | B4B-XH-A |
| 3 | 1 | K1 | 941H-2C-5D |
| 4 | 1 | LED1 | LED(赤) |
| 5 | 1 | LED2 | LED(黄) |
| 6 | 1 | PC1 | TLP624 |
| 7 | 1 | Q1 | 2SC1815 |
| 8 | 2 | R1,R2 | 3.3K |
| 9 | 3 | R3,R4,R6 | 510 |
| 10 | 1 | R5 | 10K |
| 11 | 1 | SW1 | トグルスイッチ |
制御基板
回路図にはリレーとトランジスタ、ダイオード、LED、フォトカプラ、抵抗、トグルスイッチがあります。トランジスタはGenuino101からの信号を受けてリレーのコイルを励磁するために使用しています。ダイオードはリレーのコイルに発生する逆起電力からトランジスタを保護するために、使用しています。LED1はリレーの接点側の回路の電源ランプです。LED2はリレーの接点が閉じたときに点灯します。
フォトカプラは、リレー接点の状態をGenuino101に知らせます。トグルスイッチはOnにするとリレーの接点側の回路に電源を供給します。このスイッチをOffにして接点側の回路を動作させなくする事で、疑似的な故障状態をつくれるようにしています。この回路をユニバーサル基板上に組み立てた物が、左図になります。
Arduino用ユニバーサル基板
Genuino101とは4芯のケーブルで接続します。Genuino101の上に取り付け可能なArduino用ユニバーサル基板に、コネクタと回路動作中に点灯するLEDを取り付けています(右図)。Arduino用ユニバーサル基板はGenuino101の上に取り付け可能です。
コネクタのピンアサインは下記(表)の通りです。
コネクタのピンアサイン
| コネクタのピン番号 | Genuino101の信号名 | 制御基板の信号名 |
|---|---|---|
| 1 | 5V | VCC_1 |
| 2 | A1(入力) | リレー接点信号 |
| 3 | A0(出力) | リレー励磁信号 |
| 4 | GND | GND |
すべての基板を接続したものがこちらになります。

Genuino101のプログラム
Genuino101のプログラムはArudino IDEを使って作成します。Arduino IDEはArduinoの公式ページよりダウンロードできます。ただし、Arduino IDEをインストールしただけではGenuino101のプログラム開発は出来ません。Arudino IDEでGenuino101を使える様にするには、Arudino IDEで設定する必要があります。Arduinoの公式ページの手順に従って設定します。
設定ができたらプログラムを作成します。Genuino101はRaspberry Piから動作開始の信号を受け取ってリレーの制御を開始します。リレーは3秒ごとにOn/Offを繰り返す様、制御します。動作を開始するとリレーをOn/Offする信号とフォトカプラからの信号の状態、リレーの駆動回数をRaspberry Piに知らせます。駆動回数は電源が切れても記憶させる為、EEPROMに書き込みます。そしてRaspberry Piとのやり取りはBluetoothを介して行います。
このプログラムのリストは以下の通りです。
リスト1 Genuino101のプログラム(Demo.ino)
#include // Bluetoothライブラリ
#include // タイマー割り込みライブラリ
#include // EEPROMライブラリ
#define relayPin A0 // リレー制御出力信号
#define PCPin A1 // リレー接点入力信号
BLEPeripheral blePeripheral; // BLEペリフェラルインスタンスの生成
BLEService RlyService("19B10010-E8F2-537E-4F6C-D104768A1214"); // BLEサービスの生成
// リレー制御開始用キャラクタリスティックの生成
BLECharCharacteristic actCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
// リレー接点信号用キャラクタリスティックの生成
BLECharCharacteristic sigCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead);
// リレー励磁信号用キャラクタリスティックの生成
BLECharCharacteristic rlyCharacteristic("19B10013-E8F2-537E-4F6C-D104768A1214", BLERead);
// リレー駆動回数用キャラクタリスティックの生成
BLEUnsignedIntCharacteristic cntCharacteristic("19B10014-E8F2-537E-4F6C-D104768A1214", BLERead);
// 変数の初期化
static boolean output = LOW; // リレー励磁信号
static boolean output_enb = LOW; // リレー励磁信号の出力許可
static boolean rly = LOW; // リレーの状態
static int sigValue; // リレー接点信号
static unsigned int count; // リレー駆動回数
static unsigned int eeAddress=0; // EEPROMアドレス
// リレーをOn/Offする関数
void onoff() {
output = !output; // リレー励磁信号の論理を反転
digitalWrite( relayPin, ( output & output_enb ) ); // リレー励磁信号を出力
if ( output & output_enb ) { // リレー励磁信号がHIGHレベルのとき
rly = HIGH; // リレーの状態を設定
count++; // 駆動回数をカウントアップ
cntCharacteristic.setValue( count ); // リレー駆動回数用キャラクタリスティックに値を設定
}
else { // リレー励磁信号がLOWレベルのとき
rly = LOW; // リレーの状態を設定
}
}
// setup関数
void setup() {
EEPROM.get(eeAddress, count); // EEPROMに保持している駆動回数を読み込み
pinMode( LED_BUILTIN, OUTPUT ); // オンボードLED制御信号を出力ピンに設定
pinMode( relayPin, OUTPUT ); // リレー励磁信号を出力ピンに設定
pinMode( PCPin, INPUT ); // リレー接点信号を入力ピンに設定
digitalWrite( LED_BUILTIN, LOW ); // オンボードLEDを消灯
digitalWrite( relayPin, LOW ); // リレーをOff
// ローカルネームを設定
blePeripheral.setLocalName( "RelayCtrl" );
// アドバタイズするサービスのUUIDを設定
blePeripheral.setAdvertisedServiceUuid( RlyService.uuid() );
// サービスのアトリビュートを追加
blePeripheral.addAttribute( RlyService );
// リレー制御開始用キャラクタリスティックのアトリビュートを追加
blePeripheral.addAttribute( actCharacteristic );
// リレー接点信号用キャラクタリスティックのアトリビュートを追加
blePeripheral.addAttribute( sigCharacteristic );
// リレー励磁信号用キャラクタリスティックのアトリビュートを追加
blePeripheral.addAttribute( rlyCharacteristic );
// リレー駆動回数用キャラクタリスティックのアトリビュートを追加
blePeripheral.addAttribute( cntCharacteristic );
// リレー制御開始用キャラクタリスティックの書き込みイベント発生時のコールバック関数を設定
actCharacteristic.setEventHandler(BLEWritten, actCharacteristicWritten);
// リレー制御開始用キャラクタリスティックに0を設定
actCharacteristic.setValue( 0 );
// リレー接点信号用キャラクタリスティックに0を設定
sigCharacteristic.setValue( 0 );
// リレー励磁信号用キャラクタリスティックに0を設定
rlyCharacteristic.setValue( 0 );
// リレー駆動回数用キャラクタリスティックに駆動回数を設定
cntCharacteristic.setValue( count );
// BLEペリフェラルの初期化、アドバタイズ開始
blePeripheral.begin();
// 3,000,000usごとにonoff関数を実行するように設定
CurieTimerOne.start( 3000000, &onoff );
}
// loop関数
void loop() {
// イベントをポーリング
blePeripheral.poll();
if ( rly == HIGH ) { // リレーの状態がHIGH
rlyCharacteristic.setValue( 1 ); // リレー励磁信号用キャラクタリスティックに1を設定
}
else {
rlyCharacteristic.setValue( 0 ); // リレー励磁信号用キャラクタリスティックに0を設定
}
sigValue = digitalRead( PCPin ); // リレー接点信号入力ピンを読み込み
// リレー接点信号の状態が変化していたとき
if ( sigCharacteristic.value() != sigValue ) {
// リレー接点信号用キャラクタリスティックにリレー接点信号の状態を設定
sigCharacteristic.setValue( sigValue );
}
delay( 100 ); // 100msecウェイト
}
// リレー制御開始用キャラクタリスティックの書き込みイベント用コールバック関数
void actCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic) {
// リレー制御開始用キャラクタリスティックが1のとき
if ( actCharacteristic.value() ) {
digitalWrite( LED_BUILTIN, HIGH ); // オンボードLEDを点灯
output_enb = HIGH; // リレー励磁信号の出力許可
} else {
digitalWrite( LED_BUILTIN, LOW ); // オンボードLEDを消灯
output_enb = LOW; // リレー励磁信号の出力禁止
EEPROM.update(eeAddress, count); // EEPROMに駆動回数を書き込み
}
}
それではこのプログラムを順番に説明します。
- 1~3行目:
- ライブラリを読み込んでいます。
- 5~6行目:
- 使用するピンを定義しています。
- 8行目:
- BLEペリフェラルのインスタンスを生成します。このインスタンスを使ってBleutooth通信を行います。
- 9行目:
- BLEペリフェラルが提供するサービスを生成します。今回はオリジナルのサービスを提供するので、引数には128ビットのUUIDを指定します。このプログラムではArduinoのサンプルプログラムのUUIDを流用しています。オリジナルのUUIDを指定したい場合はOnline UUID Generator(https://www.uuidgenerator.net/)というサイトがあるので、このサイトにアクセスするとUUIDを自動生成してくれます。
- 11~18行目:
- BLEペリフェラルのキャラクタリスティックを生成しています。引数にはUUIDとプロパティを指定します。プロパティにはBLERead、BLEWrite、BLENotifyが指定できます。リレー制御開始用キャラクタリスティック(actCharacteristic)はリード/ライト可能なchar型のキャラクタリスティックです。リレー接点信号用(sigCharacteristic)とリレー励磁信号用キャラクタリスティック(rlyCharacteristic)はリードを指定しています。ノーティファイを指定するとキャラクタリスティックの値に変化があった場合、セントラル側に通知するという動作を行います。今回、ノーティファイは使用していません。リレー駆動回数用キャラクタリスティック(cntCharacteristic)はリードを指定したunsigned int型のキャラクタリスティックです。
- 20~26行目:
- グローバル変数の定義と初期化を行っています。
- 29行目:
- リレーの励磁信号を制御するonoff関数です。
- 30~32行目:
- リレー励磁信号の論理を反転し、信号を出力しています。output_enb変数と論理積をとっているので、output_enb変数が真のときのみ励磁信号が出力されます。
- 34~41行目:
- リレー励磁信号がHIGHレベルのとき、リレーの状態をrly変数へ代入、駆動回数のカウントアップ、駆動回数をリレー駆動回数用キャラクタリスティックに設定しています。リレー励磁信号がLOWレベルのときはrly変数への代入のみしています。
- 45行目:
- setup関数です。
- 46行目:
- EEPROMに保持している駆動回数を読み込んでいます。
- 48~50行目:
- Genuino101で使用するピンの入出力の設定を行っています。
- 52~53行目:
- 出力ピンの出力を初期化しています。
- 55~56行目:
- ローカルネームを設定しています。Raspbian上でBluetoothデバイスをスキャンするとこの名前が表示されます。
- 57~58行目:
- アドバタイズするサービスのUUIDを設定します。
- 60~69行目:
- サービス、キャラクタリスティックをアトリビュートとして登録しています。
- 71~72行目:
- リレー制御開始用キャラクタリスティックにデータの書き込み(イベント)があった場合に呼び出すコールバック関数を設定しています。
- 74~81行目:
- 各キャラクタリスティックに初期値を設定しています。
- 83~84行目:
- BLEペリフェラルを初期化し、アドバタイズを開始します。
- 86~87行目:
- 3,000,000usごとにonoff関数を実行するように設定
- 92行目:
- loop関数です。
- 93~94行目:
- イベント(リレー制御開始用キャラクタリスティックへのデータの書き込み)をポーリングしています。
- 96~101行目:
- リレーの励磁状態により、リレー励磁信号用キャラクタリスティックに値を設定しています。
- 103行目:
- リレー接点信号の状態を読み込んでいます。
- 105~109行目:
- リレー接点信号の状態が変化していた場合に、リレー接点信号用キャラクタリスティックにリレー接点信号の状態を設定しています。
- 111行目:
- 100msecウェイトしています。
- 115行目:
- リレー制御開始用キャラクタリスティックの書き込みイベント用コールバック関数です。
- 116~119行目:
- リレー制御開始用キャラクタリスティックが1のとき、オンボードLEDを点灯し、リレー励磁信号の出力を許可しています。
- 120~123行目:
- リレー制御開始用キャラクタリスティックが0のとき、オンボードLEDを消灯、リレー励磁信号の出力を禁止し、EEPROMにリレーの駆動回数を書き込んでいます。
※次頁では、「Raspberry Piプログラム」の作成について紹介致します。


