プログラムと電気回路の勉強を兼ねて、論理回路をArduinoマイコンを使って再現してみようと思います。まずは基本の論理回路であるNOT・AND・ORからやってみます。
基本的な考え方として、
考え方
- 論理入力は、タクトスイッチのON-OFFをdigitalReadする。
- 論理出力は、LEDの点灯・消灯で表す。
- 各基本回路は関数として作成し、loop関数内から呼び出す形で実行する。
という前提で行きます。そんなことをして何の意味があるのか?という素直な疑問が湧きますが、気にしないことにします。
NOT回路
結果1 とりあえず動くプログラム
#define s1 7 #define LED 13 void setup() { pinMode(s1, INPUT_PULLUP); //スイッチは内部プルアップを利用して接続 pinMode(LED, OUTPUT); } void loop(){ NOT(s1,LED); } //NOT回路の関数 //引数として入出力ピン番号を指定できるようにした void NOT(int inpin, int outpin) { int a; a = digitalRead(inpin); digitalWrite(outpin, a); }
上記プログラムで、NOT動作するプログラムになりました。しかしこれだと拡張性がないので、
もう少し拡張性をもたせる
- スイッチからの入力だけでなく、他の論理回路の出力値を受け取って入力とする場合にも対応する(変数で動作モードを設定すれば対応できそう)
- ということは、この関数の出力も値として取得したいので、戻り値として返すようにする
以上の観点で改良してみました。
結果2 拡張したNOT回路
#define s1 7 #define LED 13 #define L1 12 void setup() { pinMode(s1, INPUT_PULLUP); //スイッチは内部プルアップを利用して接続 pinMode(LED, OUTPUT); pinMode(L1,OUTPUT); } void loop(){ NOT(1,s1,LED); NOT(2,NOT(1,s1,L1),LED); //このように入れ子で実行できる //この場合NOTのNOTなので入力=出力になる } //mode=1で通常動作 mode=2の場合は値を渡してそれをNOTする動作 //出力はint型で返すようにする int NOT(int mode, int inp, int outpin) { int a; switch (mode) { case 1: a = digitalRead(inp); digitalWrite(LED, a); break; case 2: a = inp; a = !a; digitalWrite(outpin, a); break; } return a; }
このようにして、引数としてモードを設定する値を指定してやります。モード1ならスイッチからの入力、モード2なら値として入力値を渡します。
AND回路
結果
//setup及びloop関数は省略 int AND(int mode, int inp1, int inp2, int outpin) { int a; switch (mode) { case 1: if (digitalRead(inp1) == 0 && digitalRead(inp2) == 0) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } break; case 2: if (inp1 == 1 && inp2 == 1) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } } return a; }
関数の部分のみを記載しています。NOT回路と共通の考え方で、mode=1のときはスイッチの状態を入力とし、mode=2のときは値として入力値を渡して結果を返します。
OR回路
結果
setup,loop関数は省略 int OR(int mode, int inp1, int inp2, int outpin) { int a; switch (mode) { case 1: if (digitalRead(inp1) == 0 || digitalRead(inp2) == 0) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } break; case 2: if (inp1 == 1 || inp2 == 1) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } } return a; }
こちらも考え方は同じ。これで基本の3回路が揃いました。
組み合わせ回路を再現する
上記の3つの基本回路を利用して、NAND回路3つの組み合わせ回路を再現してみます。
回路図

上記回路は一見複雑ですが、実はOR回路です。NAND回路を3つ組み合わせるとOR回路に変換できます、的なアレです。
プログラム
#define s1 3 #define s2 4 #define LED 13 #define L1 12 #define L2 11 #define L3 10 #define L4 9 #define L5 8 void setup() { pinMode(s1, INPUT_PULLUP); pinMode(s2, INPUT_PULLUP); pinMode(LED, OUTPUT); pinMode(L1,OUTPUT); pinMode(L2,OUTPUT); pinMode(L3,OUTPUT); pinMode(L4,OUTPUT); pinMode(L5,OUTPUT); } void loop() { //回路一つずつ実行して変数に代入していく方法 /*int a = AND(1, s2, s2, l2); int b = AND(1, s2, s2, l3); int a1 = NOT(2, a, l4); int b1 = NOT(2, b, l5); int c = AND(2, a1, b1, l6); NOT(2, c, LED);*/ //一行で一気に書くとこうなる NOT(2,AND(2,NOT(2,AND(1,s1,s1,l2),l4),NOT(2,AND(1,s2,s2,l3),l5),l6),LED); } int NOT(int mode, int inp, int outpin) { int a; switch (mode) { case 1: a = digitalRead(inp); digitalWrite(LED, a); break; case 2: a = inp; a = !a; digitalWrite(outpin, a); break; } return a; } int AND(int mode, int inp1, int inp2, int outpin) { int a; switch (mode) { case 1: if (digitalRead(inp1) == 0 && digitalRead(inp2) == 0) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } break; case 2: if (inp1 == 1 && inp2 == 1) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } } return a; } int OR(int mode, int inp1, int inp2, int outpin) { int a; switch (mode) { case 1: if (digitalRead(inp1) == 0 || digitalRead(inp2) == 0) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } break; case 2: if (inp1 == 1 || inp2 == 1) { a = 1; digitalWrite(outpin, a); } else { a = 0; digitalWrite(outpin, a); } } return a; } int NAND(int mode, int inp1, int inp2, int outpin) { int a; switch (mode) { case 1: if (digitalRead(inp1) == digitalRead(inp2)) { a = 0; digitalWrite(outpin, a); } else { a = 1; digitalWrite(outpin, a); } break; case 2: if (inp1 == inp2) { a = 0; digitalWrite(outpin, a); } else { a = 1; digitalWrite(outpin, a); } } return a; }
えらく長いですが、こんな感じになりました。回路一つ一つを順に実行して行き、結果を変数に格納しながら順次進めていく方法と、関数同士を入れ子にして一気に実行する方法と、どちらでも動かすことができました。
Tips!
各基本回路の出力ピンを別々に設定しているので、それぞれにLEDを接続しておけば、出力の途中経過を目で確認出来るようになります。
現状だと出力のフィードバックに関数レベルで対応できてない気がするので、もう少し改良の余地がありそうです。引き続き勉強してみることにします。