Intel Edison/Galileo Gen 2等でHC-SR04を8個同時接続してみる

はじめに

先日のメモで超音波距離センサー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はTrigEchoという2つの信号の制御が必要で、それぞれデジタル・ピンでアクセスする必要があります。

HC-SR04のおもて側写真

Intel Edison/Galileo Gen 2※10は、デジタル・ピンを13ピン備えていますので、すべてのピンを使ったとしても最大で6つのHC-SR04しか接続できません。

そこで直接TrigEchoにアクセスするのではなく、対象のセンサーを8個のうち1つ選び、その上でそのセンサーに対してのみTrigEchoにアクセスできるようにしたいと思います。

超音波距離センサーを選択する方法

複数の信号を出力するために用いられる、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にはそのまま入れることができません。そこで、この信号のHIGHLOWを入れ替えるロジック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ピンのパッケージで以下のようなピン・アサインとなっています:

ロジックIC 7404N

この三角に○がついたマークは「インバーター」を意味していて、NOT演算を行います。つまり、HIGH信号を入力するとLOW信号を出力し、LOW信号を入力するとHIGH信号を出力します。この回路が1つのチップに6個入っています。

74HC138 : 3-Line To 8-Line Decoders/Demultiplexers

このロジックICは16ピンのパッケージで以下のようなピン・アサインとなっています:

ロジックIC 74138

ABおよびCの3ビットの入力を受けて、それに対応するY0からY7のいずれかをLOWに選択する動作を基本とします。ただし、G1HIGHではないか、G2AあるいはG2BLOWではない場合には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ピンのパッケージで以下のようなピン・アサインとなっています:

ロジックIC 74HC4078

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

HC-SR04のTrig選択ロジック

それぞれのロジックICのVCCのすぐ近くに0.1μFのコンデンサーを挿入し、その両足をVCCGNDに接続するようにします。これはロジックICが安定して動くようにするおまじないです。詳しくは「バイパス・コンデンサー」で検索して調べてみてください。

続いてTrig0からTrig7を発光ダイオードのアノード側(足の長い方)に接続して、カソード側(足の短い方)は1kΩの抵抗経由でGNDへ落とします。この時、Trig0からTrig7までの発光ダイオードの順番を番号順にします。今回の回路では1回に1つの発光ダイオードのみが点灯対象となるため、1本の1kΩの抵抗にすべての発光ダイオードのカソードを集約してGNDに落とすように接続して問題ありません。

残りのD2からD5はIntel Galileo Gen 2などのデジタル・ピンの該当する番号のピンへ接続します:

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個ずつ選択されることが確認できたので、発光ダイオードへつなげたジャンパー・ワイヤーを取り除きます。そしてブレッド・ボードを増設して、VCCGNDを配線します。そこへ74HC4078を以下のように配線します:

HC-SR04のEcho集約ロジック

そして先ほどのTrig0からTrig7と追加した74HC4078の各ピンに割り当てたEcho0からEcho7VCCGNDの4本を1セットとして各HC-SR04に配線します。なお、Trig0からTrig7は正確にこの順番で接続する必要がありますが、Echo0からEcho7はどこにどのセンサーからのEchoを接続しても構いません。

ただ、8個のセンサーをそのまま接続しても何が何だかわからない状況に陥るので、今回私は段ボール紙にセンサーを取り付けることにしました。まず、Adobe Illustratorを使用してHC-SR04の形を原寸で作成し、それを8個並べた図を作ります。それを印刷して段ボール紙に張り付けて、アート・ナイフでくり抜きました:

HC-SR04の形にくり抜き中

HC-SR04とその形にくり抜いた紙

横に4個、縦2列で8個のセンサーを段ボール紙をくり抜いて取り付けました:

8個のHC-SR04を取り付けたIntel Galileo Gen 2ボード

8個のHC-SR04を取り付けた段ボール紙

上の段がそれぞれ03のHC-SR04、下の段が同様に47の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);
}

このスケッチを動かして少し先に工作用紙を置いて距離を測ってみた結果、「シリアルモニタ」に出力されたログの抜粋を以下に示します:

8個のHC-SR04を接続しての動作テスト

~ 前略 ~
[ 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Ωの抵抗はすべてジャンパー代わりに使用したものです。ジャンパーに置き換えて問題ありません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です