プログラムと電気回路の勉強を兼ねて、論理回路を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を接続しておけば、出力の途中経過を目で確認出来るようになります。
現状だと出力のフィードバックに関数レベルで対応できてない気がするので、もう少し改良の余地がありそうです。引き続き勉強してみることにします。