こんにちは、ENGかぴです。
Arduinoは機能が充実しているためLCDや7セグメントLEDを使用しているとデジタルピンが不足することがあります。マルチプレクサを使うことでDIの不足を補うことができます。マルチプレクサでDIを拡張する方法をまとめました。
本記事はArduinoのDIをマルチプレクサで拡張しスイッチの状態変化を7セグメントLEDに表示することを目的としています。マルチプレクサは74HC4051APを使用しています。
Arduino UNOを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
DIをマルチプレクサで拡張する
マルチプレクサは8つのスイッチを切り替えて使用する部品です。スイッチの片方はコモン(COM)でありマイコンのデジタルピンに接続することで8つの入力を切り替えながら入力することができます。
マルチプレクサのCOMにDIとDOのどちらでも接続はできますが、DOで使用する場合は出力の保持ができないので注意が必要です。
マルチプレクサのスイッチ出力の切り替え

マルチプレクサはINHをLにするとデバイスが動作開始します。A、B、Cで0~7のチャンネルを切り替えて共通のCOMに入力します。マイコンのDIにCOMを接続するとA、B、Cで指定したチャンネルのDI情報をCOMを介して受けることができます。
PR:RUNTEQ(ランテック )- マイベスト3年連続1位を獲得した実績を持つWebエンジニア養成プログラミングスクール
マルチプレクサを制御する
マルチプレクサを使用するための初期化とビット操作について説明します。ArduinoのA0~A5はアナログ入力ピンとデジタルピンを兼用しているため今回はA0~A3をマルチプレクサ用のピンとして使用します。
#define PIN_MUL_DOA 14 //A0でもよい
#define PIN_MUL_DOB 15 //A1でもよい
#define PIN_MUL_DOC 16 //A2でもよい
#define PIN_DI1 17 //A3でもよい
void setup(){
pinMode(PIN_DI1,INPUT_PULLUP); //マルチプレクサのCOMに接続
pinMode(PIN_MUL_DOA,OUTPUT); //マルチプレクサのAに接続
pinMode(PIN_MUL_DOB,OUTPUT); //マルチプレクサのBに接続
pinMode(PIN_MUL_DOC,OUTPUT); //マルチプレクサのCに接続
}
マルチプレクサの信号の切り替えはA、B、Cによって制御するためマイコンでDOを3つ準備します。マルチプレクサのCOMをマイコンのDIに取り込むためにマイコン内蔵のプルアップ付きのDIとして初期化を行います。
uint8_t di[MUL_MAX];
void loop(){
uint8_t mulmode;
bool loopflg = true;
mulmode = MUL_0;
do{
MulDiCng(mulmode); //マルチプレクサの制御
delayMicroseconds(10); //10us切り替え後の遅延
di[ mulmode ] = digitalRead(PIN_DI1);
if( ++mulmode >= MUL_MAX){
loopflg = false;
}
}while(loopflg);
}
マルチプレクサの制御の例を示しています。関数MulDiCng()をコールしてマルチプレクサの制御を切り替えています。切り替えた後は信号安定化のため10usウェイトを置いています。
上の例では、ウェイト後に0ピン(PIN_DI1)を読み込んでいますが、外部信号を取り込む場合はチャタリングなどによって信号が安定しないことがあるためフィルタ処理を追加することがあります。チャタリング防止の方法については下記記事にまとめています。
Arduino環境でのタイマ管理とDIのチャタリング防止の方法
ソースコード全体では4回一致のフィルタを実装しています。
#define USE_BITS 3 //3ビット使用する
/* Led7Seg pattern function add */
void MulDiCng(uint8_t no){
uint8_t i;
uint8_t bit;
for( i=0; i < USE_BITS; i++){
bit = 1 << i;
if( bit & no){ //ビットが立っているかの確認
digitalWrite(i + PIN_MUL_DOA, HIGH);
}
else{
digitalWrite(i + PIN_MUL_DOA, LOW);
}
}
}
引数に0~7までの値を指定し引数の値に応じて下位ビットから順にビットが立っているかの確認を行い、ビットが立っている場合はDOにHをセットします。引数に3を指定した場合を例にして説明します。
例)引数に3を指定した場合
0x03と0x01の論理積は1なので14ピン(PIN_MUL_DOA)がHとなる。
0x03と0x02の論理積は1なので15ピン(PIN_MUL_DOB)がHとなる。
0x03と0x04の論理積は0なので16ピン(PIN_MUL_DOC)がLとなる。
0x03と各ビットの論理積が1であれば対象のDOにHをセットし0であればLをセットするようにします。真理値表によるとAとBがHとなるため3が出力対象になりCOMと接続されます。
PR:わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!
7セグメントLEDの表示パターンを追加

7セグメントLEDの使い方や表示パターンの作り方については下記記事にまとめています。
表示パターンを0~9だけでなく「A、b、c、d、E、F、ー」を追加します。表示パターンは7セグメントLEDのa~gまでの各LEDに対して点灯させたい箇所を1として2進数で並べて16進数に変換した値をパターンとして準備しています。
#define LED7SEG_NEGATIVE //負論理の時コメントアウトを外す
byte Seg7Set[17]={ 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x27, 0x7F, 0x6F,
0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40};// A,b,C,d,E,F,-
void setup(){
#ifdef LED7SEG_NEGATIVE
for(uint8_t i=0; i < sizeof(Seg7Set); i++){
Seg7Set[i] = (~Seg7Set[i] & 0x7F); //負論理の7セグメントLEDの場合に反転する
}
#endif
}
7セグメントLEDの表現方式から大文字と小文字が混在していますが、このパターンによって16進数での表現が可能となります。
7セグメントLEDのLEDの極性がLOWアクティブのものを使っている場合はSeg7Set[]内のパターンを論理反転して使用します。
動作確認

ArduinoのA0~A3をマルチプレクサ用のDIOに接続しています。A0~A2をマルチプレクサの切り替えの制御に使用しA3をDIにしています。DIはマイコンの内蔵プルアップを使用しているため抵抗によるプルアップを実装していません。
C1はマルチプレクサの電源間のバイパスコンデンサとして使用しています。ロジックICなどは電源間に0.1uF程度のバイパスコンデンサを実装するのが一般的です。
SW1とSW2をONするとLになるようにしています。マルチプレクサによってSWの情報がArduinoのDIに入力されます。DIは内部プルアップ付きのDIとしているためSWをONしていない箇所においてはHとなります。

SWを操作したときの状態変化を検出して7セグメントLEDにできていることが確認できました。
ソースコード全体
ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。
リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。
関連リンク
Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
最後まで、読んでいただきありがとうございました。