はじめに
先日のメモで超音波距離センサーHC-SR04を扱うためのArduino IDE 1.5系用のライブラリーを作成しましたが、今回はこれを用いながら8個のHC-SR04を同時に接続して使用してみたいと思います。
ところでなんで8つのHC-SR04を接続するの?
私が別件で使用したいと考えているからです。それを今回試作してみたので、メモとしてこの記事を作成しました。別件の内容はそのうち公開するかもしれません。ちゃんと完成させられれば…ですが。※1
今回使用するもの
- Intel Galileo Gen 2ボード(他にもIntel Edison Board for ArduinoやArduino Uno R3および互換ボードでも全く問題なく動作します)※2
- 超音波距離センサーHC-SR04 – 8つ
- ロジックIC 74HC04N – 2つ※3
- ロジックIC 74HC138※4
- ロジックIC 74HC4078※5
- バイパス・コンデンサー 0.1μF – 4つ※6
- 抵抗 1kΩ×6を使っていますが、ジャンパー・ワイヤー代わりに使用しているだけなのでなくて構いません。※7
- ジャンパー・ワイヤー(オス・オス) – 必要な数
- ジャンパー・ワイヤー(オス・メス) – 32本
- ブレッド・ボード(レギュラー・サイズ) – 必要な枚数※8
- 発光ダイオード(LED) – 8本
- 発光ダイオード用抵抗 – 1本※9
- ブレッド・ボード(小さいもの) – 1枚
後半3つはロジックICによる回路を発光ダイオードで確認する必要がなければ不要です。
8個のHC-SR04を接続する
基本的な考え方
HC-SR04はTrig
とEcho
という2つの信号の制御が必要で、それぞれデジタル・ピンでアクセスする必要があります。
Intel Edison/Galileo Gen 2※10は、デジタル・ピンを13ピン備えていますので、すべてのピンを使ったとしても最大で6つのHC-SR04しか接続できません。
そこで直接Trig
とEcho
にアクセスするのではなく、対象のセンサーを8個のうち1つ選び、その上でそのセンサーに対してのみTrig
とEcho
にアクセスできるようにしたいと思います。
超音波距離センサーを選択する方法
複数の信号を出力するために用いられる、Arudino系で定番な方法はshiftOut
命令とロジックIC「74HC595」を組み合わせるものです。これはシリアル(ビット単位)でデータを出力し、8ビットのパラレル出力を生成する方法です。さらに必要に応じて74HC595の段数を増やして、ビット数を増加させることもできます。しかし、この方法では特定のHC-SR04のTrig
だけを10μs※11の間HIGH
にして、すぐにLOW
にするといった操作は苦手です。
そこで今回は、別のロジックIC「74HC138」を使用することにしました。74HC138は3本の選択信号と3本の制御信号により、8個の選択肢のうち1つを選択するための信号を出すことができます。制御信号は選択した対象へ信号を出す、出さないの制御ができるため、対象となるHC-SR04のTrig
にだけ10μsの間HIGH
を出すという制御が容易です。
ただし、74HC138の選択信号はLOW
をアクティブとして出力する「負論理※12」であるため、HC-SR04にはそのまま入れることができません。そこで、この信号のHIGH
とLOW
を入れ替えるロジックIC「74HC04N」を使用します。この74HC04Nは1つのチップの中に6つのNOT回路が入っていますが、今回は8信号を扱うため74HC04Nを2つ使用します。※13
8つのHC-SR04からのEcho
信号の扱い
続いてHC-SR04から出力されるEcho
信号の扱いを考えてみます。
今回は8つのHC-SR04を接続しますが、時間単位で見れば1つしか使用しません(Trig
信号も同時に1つのHC-SR04へしか接続されません)。つまり、Echo
信号は同時に複数のセンサーから出力されることはなく、常に1個のセンサーからしか出力されません。このため、Echo
信号を8本分取りまとめて1つ信号に合成して出力することにします。
この信号の合成には、8入力1出力のNOR/OR回路を搭載するロジックIC「74HC4078」を使用します。※14
ロジックICの仕様
74HC04N : Hex Inverters
このロジックICは14ピンのパッケージで以下のようなピン・アサインとなっています:
この三角に○がついたマークは「インバーター」を意味していて、NOT演算を行います。つまり、HIGH
信号を入力するとLOW
信号を出力し、LOW
信号を入力するとHIGH
信号を出力します。この回路が1つのチップに6個入っています。
74HC138 : 3-Line To 8-Line Decoders/Demultiplexers
このロジックICは16ピンのパッケージで以下のようなピン・アサインとなっています:
A
、B
およびC
の3ビットの入力を受けて、それに対応するY0
からY7
のいずれかをLOW
に選択する動作を基本とします。ただし、G1
がHIGH
ではないか、G2A
あるいはG2B
がLOW
ではない場合にはY0
からY7
のすべてがHIGH
になります。
入力と出力の関係をまとめた表を以下に示します:
入力 | 出力 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
G1 |
G2B |
G2A |
C |
B |
A |
Y0 |
Y1 |
Y2 |
Y3 |
Y4 |
Y5 |
Y6 |
Y7 |
L |
* |
* |
* |
* |
* |
H |
H |
H |
H |
H |
H |
H |
H |
H |
H |
* |
* |
* |
* |
H |
H |
H |
H |
H |
H |
H |
H |
H |
L |
H |
* |
* |
* |
H |
H |
H |
H |
H |
H |
H |
H |
H |
L |
L |
L |
L |
L |
L |
H |
H |
H |
H |
H |
H |
H |
H |
L |
L |
L |
L |
H |
H |
L |
H |
H |
H |
H |
H |
H |
H |
L |
L |
L |
H |
L |
H |
H |
L |
H |
H |
H |
H |
H |
H |
L |
L |
L |
H |
H |
H |
H |
H |
L |
H |
H |
H |
H |
H |
L |
L |
H |
L |
L |
H |
H |
H |
H |
L |
H |
H |
H |
H |
L |
L |
H |
L |
H |
H |
H |
H |
H |
H |
L |
H |
H |
H |
L |
L |
H |
H |
L |
H |
H |
H |
H |
H |
H |
L |
H |
H |
L |
L |
H |
H |
H |
H |
H |
H |
H |
H |
H |
H |
L |
74HC4078 : 8-Input NOR/OR Gate
このロジックICは14ピンのパッケージで以下のようなピン・アサインとなっています:
8つの入力から1つのNOR演算の結果および1つのOR演算の結果を出力します。「N.C.」は「No Connect」の略で、何も接続されていない未使用ピンであることを意味します。
OR演算とは、いくつかある入力のうち、いずれかがHIGH
であれば出力がHIGH
となる演算です。すべての入力ががLOW
であれば出力はLOW
となります。
NOR演算とは、いくつかある入力のうち、いずれかがHIGH
であれば出力がLOW
となる演算です。すべての入力がLOW
であれば出力はHIGH
となります。ちょうどOR演算の出力を逆にしたのと同じです。つまり、NOT OR演算=NOR演算ということです。
組み立ててみる
74HC138と74HC04Nで選択状況を発光ダイオードで確認
まず、ロジックICを使用した回路を実際に接続して、その出力を発光ダイオードで可視化して確認してみます。以下のようにブレッド・ボード上でロジックICを接続します:※15
それぞれのロジックICのVCC
のすぐ近くに0.1μFのコンデンサーを挿入し、その両足をVCC
とGND
に接続するようにします。これはロジックICが安定して動くようにするおまじないです。詳しくは「バイパス・コンデンサー」で検索して調べてみてください。
続いてTrig0
からTrig7
を発光ダイオードのアノード側(足の長い方)に接続して、カソード側(足の短い方)は1kΩの抵抗経由でGND
へ落とします。この時、Trig0
からTrig7
までの発光ダイオードの順番を番号順にします。今回の回路では1回に1つの発光ダイオードのみが点灯対象となるため、1本の1kΩの抵抗にすべての発光ダイオードのカソードを集約してGND
に落とすように接続して問題ありません。
残りのD2
からD5
はIntel Galileo Gen 2などのデジタル・ピンの該当する番号のピンへ接続します:
そして以下のスケッチをArduino IDEからIntel Galileo Gen 2などに転送します:
void setup() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
}
void loop() {
for(int j = 0; j <= 1; j++) {
digitalWrite(5, j ? HIGH : LOW);
for(int i = 0; i <= 7; i++) {
digitalWrite(2, (i & 1) ? HIGH : LOW);
digitalWrite(3, (i & 2) ? HIGH : LOW);
digitalWrite(4, (i & 4) ? HIGH : LOW);
delay(200);
}
}
}
これを実行すると以下のように順番に発光ダイオードが光るのが確認できます:
HC-SR04を8個接続する
1個ずつ選択されることが確認できたので、発光ダイオードへつなげたジャンパー・ワイヤーを取り除きます。そしてブレッド・ボードを増設して、VCC
とGND
を配線します。そこへ74HC4078を以下のように配線します:
そして先ほどのTrig0
からTrig7
と追加した74HC4078の各ピンに割り当てたEcho0
からEcho7
、VCC
、GND
の4本を1セットとして各HC-SR04に配線します。なお、Trig0
からTrig7
は正確にこの順番で接続する必要がありますが、Echo0
からEcho7
はどこにどのセンサーからのEcho
を接続しても構いません。
ただ、8個のセンサーをそのまま接続しても何が何だかわからない状況に陥るので、今回私は段ボール紙にセンサーを取り付けることにしました。まず、Adobe Illustratorを使用してHC-SR04の形を原寸で作成し、それを8個並べた図を作ります。それを印刷して段ボール紙に張り付けて、アート・ナイフでくり抜きました:
横に4個、縦2列で8個のセンサーを段ボール紙をくり抜いて取り付けました:
上の段がそれぞれ0
~3
のHC-SR04、下の段が同様に4
~7
のHC-SR04です。
これら8個のセンサーを駆動させるスケッチ(“超音波距離センサーHC-SR04をIntel Edison/Galileoで使ってみる”で公開している私の作成したArduino IDE 1.5系対応のHC-SR04用のライブラリーを使用しています)を以下に示します:
#include <hc_sr04.h>
HC_SR04* hc_src04;
void setup() {
Serial.begin(115200);
hc_src04 = new HC_SR04(5, 6);
hc_src04->setTemperature(25.0f);
Serial.print("Speed of sound : ");
Serial.print(hc_src04->getSoundSpeed(), 4);
Serial.println("m");
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
}
void loop() {
float distance;
double summary = 0.0f;
Serial.print("[ ");
for(int i = 0; i < 8; i++) {
Serial.print(i);
Serial.print("=");
digitalWrite(2, (i & 1) ? HIGH : LOW);
digitalWrite(3, (i & 2) ? HIGH : LOW);
digitalWrite(4, (i & 4) ? HIGH : LOW);
distance = hc_src04->getDistance();
summary += distance;
Serial.print(distance, 4);
Serial.print("cm ");
}
Serial.print("avl=");
Serial.print(summary / 8.0f, 4);
Serial.println("cm ]");
delay(1000);
}
このスケッチを動かして少し先に工作用紙を置いて距離を測ってみた結果、「シリアルモニタ」に出力されたログの抜粋を以下に示します:
~ 前略 ~
[ 0=39.5810cm 1=38.8884cm 2=38.6806cm 3=37.3820cm 4=38.7152cm 5=39.9965cm 6=37.7802cm 7=37.3993cm avl=38.5529cm ]
[ 0=39.5983cm 1=38.9057cm 2=38.6979cm 3=37.3820cm 4=38.7152cm 5=39.9965cm 6=37.7802cm 7=37.3820cm avl=38.5572cm ]
[ 0=39.5810cm 1=38.4901cm 2=38.2824cm 3=37.3993cm 4=39.1481cm 5=39.9965cm 6=37.7802cm 7=36.9838cm avl=38.4577cm ]
[ 0=39.5810cm 1=38.9230cm 2=38.6806cm 3=37.3820cm 4=39.1308cm 5=39.5636cm 6=38.6806cm 7=37.3820cm avl=38.6655cm ]
[ 0=39.1654cm 1=38.9057cm 2=37.8495cm 3=36.9665cm 4=38.7152cm 5=39.9792cm 6=38.2477cm 7=36.9665cm avl=38.3495cm ]
[ 0=39.1827cm 1=38.4901cm 2=37.8668cm 3=36.9665cm 4=39.1308cm 5=39.9965cm 6=38.2477cm 7=36.9665cm avl=38.3560cm ]
[ 0=39.5810cm 1=38.4901cm 2=37.8668cm 3=36.9665cm 4=39.1308cm 5=39.9792cm 6=38.2477cm 7=36.9665cm avl=38.4036cm ]
[ 0=39.5810cm 1=38.4901cm 2=37.8495cm 3=36.9838cm 4=39.1308cm 5=39.5636cm 6=38.2477cm 7=36.9665cm avl=38.3516cm ]
[ 0=39.5810cm 1=38.4901cm 2=37.8668cm 3=36.5682cm 4=39.1308cm 5=39.5636cm 6=38.2477cm 7=36.9665cm avl=38.3018cm ]
[ 0=39.5810cm 1=38.0746cm 2=38.8191cm 3=36.9665cm 4=38.7152cm 5=39.9792cm 6=38.1958cm 7=36.9838cm avl=38.4144cm ]
[ 0=39.5983cm 1=38.4382cm 2=38.6979cm 3=37.3820cm 4=39.1308cm 5=39.5636cm 6=38.2477cm 7=37.3820cm avl=38.5551cm ]
[ 0=39.1827cm 1=38.0227cm 2=38.2824cm 3=37.3820cm 4=39.1308cm 5=39.5810cm 6=38.2477cm 7=36.9665cm avl=38.3495cm ]
[ 0=39.2000cm 1=38.4901cm 2=38.2651cm 3=37.3993cm 4=39.5983cm 5=39.5636cm 6=38.6633cm 7=36.9318cm avl=38.5140cm ]
[ 0=39.1654cm 1=38.4901cm 2=38.2824cm 3=37.3647cm 4=39.1827cm 5=39.5810cm 6=38.2477cm 7=36.9318cm avl=38.4057cm ]
[ 0=39.1827cm 1=38.8884cm 2=38.6806cm 3=36.8972cm 4=39.5983cm 5=39.5810cm 6=38.1958cm 7=36.9145cm avl=38.4923cm ]
[ 0=39.1827cm 1=38.9230cm 2=37.7976cm 3=36.9145cm 4=39.1308cm 5=40.4121cm 6=37.7802cm 7=36.9318cm avl=38.3841cm ]
[ 0=39.1827cm 1=38.4901cm 2=38.2651cm 3=36.9145cm 4=39.6156cm 5=39.9965cm 6=38.1958cm 7=36.9145cm avl=38.4469cm ]
~ 以下略 ~
このように8個のHC-SR04で計測した距離とその平均距離を出力します。それぞれの近いセンサー、特に上下の位置関係を持つセンサーは非常に近い距離を検出しており、各センサーのばらつきは少なく、個体差はあまりないようです。それと同時に、今回作成した回路で8個のHC-SR04を5つのデジタル・ピンだけで操作できていることが確認できました。
まとめ
最初に書いたように、今回作成した8つのHC-SR04を動作させるこの回路は私自身がとある目的のために試作してみたものです。ですが、実用性はともかく、それなりに参考にしていただける点もあるのではないかと思い公開してみました。ロジックICを使ったことがない方が「ほぉ、こんな風に使えるんだ...」と思っていただければという感じで作成しました。
私はと言えば、子供のころにロジックICやその他いろいろ組み合わせて自作していた思い出があふれてきました 🙂 懐かしいような、なんという、不思議な感じですね。
なお、今回使用している74HC系はCMOSと呼ばれる分類のもので、静電気に弱いのでその点はご注意ください。また使用しない入力ピンは必ずHIGH
またはLOW
に接続しておく必要がありますので、この点もご注意ください。面倒なのであれば74LS系を使うという手もあります。
- 大したものを作っているわけではありませんので、期待しないでください。思ったようにできなければお蔵入りするかもしれません。
- Intel Galileo Gen 1ボードでは動作しません。
- メーカーは問いません。今回はTexas Instrumentsのものを使用しました。74LS04Nでも大丈夫でしょう。
- メーカーは問いません。今回は東芝 セミコンダクター&ストレージ社のものを使用しました。74LS138でも大丈夫でしょう。
- メーカーは問いません。今回は東芝 セミコンダクター&ストレージ社のものを使用しました。
- 今回くらいの規模であればなくても動くでしょう。
- “Intel Edison Module用「AE-Edison-BASE64」を使ってみる”と同時にやっていたのでジャンパー・ワイヤーが足りなくなって問題のない個所に抵抗を使っていたのです。
- 今回はレギュラー・サイズのブレッド・ボードを2枚連結したものを使用しました。
- 今回は1kΩの抵抗を使用しました。
- その原型となったArduino Uno R3とその互換ボードも同じです。
- μs = マイクロ秒 = 1,000,000分の1秒。
HIGH
信号を有効あるいは1
とし、LOW
信号を無効あるいは0
として扱うことを「正論理」といいます。逆にHIGH
信号を無効あるいは0
とし、LOW
信号を有効あるいは1
として扱うことを「負論理」といいます。- 1つの74HC04Nに6つのNOT回路が入っているので、2つの74HC04Nで12つのNOT回路が使用できることになります。
- これはもともと「4078」と呼ばれていた4000シリーズ系のロジックICのピン互換で74HC信号互換のものです。
- の接続図に存在する1kΩの抵抗はすべてジャンパー代わりに使用したものです。ジャンパーに置き換えて問題ありません。