Arduinoで7セグメントLED4桁を表示(ATmega328)
2019/07/25
Arduino(ATmega328)で7セグメントLED4桁を表示させてみました。数字がカウントされる様子はまるで時限爆弾のようです。どの色の線を切れば・・・という感じでしょうか。
プログラム通りにLEDが点灯するのは見ていて気持ちが良いです。これができれば後はプログラム次第で何でもできる感じがします。
使用したのはダイナミック接続4桁高輝度赤色7セグメントLED表示器 カソードコモン(カソード共通接続)です。
一桁を高速に切り替えて4桁分を表示するダイナミック点灯を使います。
Arduino Unoに接続するピンはアノード側に抵抗を8本(今回は120Ω)付け、カソードは直結です。後でATmega328を単体で動かすためのピン番号も併記しておきます。
Arduino | ATmega328 | 接続 | 7seg | Segment |
2 | 4 | 120Ω | 1 | E |
3 | 5 | 120Ω | 2 | D |
4 | 6 | 120Ω | 3 | DP |
5 | 11 | 120Ω | 4 | C |
6 | 12 | 120Ω | 5 | G |
7 | 13 | 直結 | 6 | DIG4 |
8 | 14 | 120Ω | 7 | B |
9 | 15 | 直結 | 8 | DIG3 |
10 | 16 | 直結 | 9 | DIG2 |
11 | 17 | 120Ω | 10 | F |
12 | 18 | 120Ω | 11 | A |
13 | 19 | 直結 | 12 | DIG1 |
スケッチです。「0000」~「9999」を1づつカウントして繰り返します。
const int anode_pins[] = {12, 8, 5, 3, 2, 11, 6, 4}; // A B C D E F G DP const int cathode_pins[] = {7, 9, 10, 13}; // DIG4 DIG3 DIG2 DIG1 const int number_of_anode_pins = sizeof(anode_pins) / sizeof(anode_pins[0]); const int number_of_cathode_pins = sizeof(cathode_pins) / sizeof(cathode_pins[0]); int numbers_to_display = 0; // LEDに表示する数字を保持する変数 const int digits[] = { 0b00111111, // 0 0b00000110, // 1 0b01011011, // 2 0b01001111, // 3 0b01100110, // 4 0b01101101, // 5 0b01111101, // 6 0b00100111, // 7 0b01111111, // 8 0b01101111, // 9 }; // 1桁の数字(n)を表示する void display_number (int n) { for (int i = 0; i < number_of_anode_pins; i++) { digitalWrite(anode_pins[i], digits[n] & (1 << i) ? HIGH : LOW); } } // アノードをすべてLOWにする void clear_segments() { for (int j = 0; j < number_of_anode_pins; j++) { digitalWrite(anode_pins[j], LOW); } } void display_numbers () { int n = numbers_to_display; // number_to_displayの値を保持し変数にコピー for (int i = 0; i < number_of_cathode_pins; i++) { digitalWrite(cathode_pins[i], LOW); display_number(n % 10); // 最後の一桁を表示する delayMicroseconds(100); clear_segments(); digitalWrite(cathode_pins[i], HIGH); n = n / 10; // 10で割る } } void set_numbers(int n) { numbers_to_display = n; } // 初期設定 void setup() { for (int i = 0; i < number_of_anode_pins; i++) { pinMode(anode_pins[i], OUTPUT); // anode_pinsを出力モードに } for (int i = 0; i < number_of_cathode_pins; i++) { pinMode(cathode_pins[i], OUTPUT); // cathode_pinを出力モードに digitalWrite(cathode_pins[i], HIGH); } // f = クロック周波数 / ( 2 * 分周比 * ( 1 + 比較レジスタの値)) // 分周比=32, 比較レジスタの1値=255 -> f = 16000000 / (2 * 32 * 256) = 976 Hz OCR2A = 255; // 255クロックごとに割り込みをかける TCCR2B = 0b100; // 分周比を32に設定する bitWrite(TIMSK2, OCIE2A, 1); // TIMER2を許可する } void loop () { for (int i = 0; i < 10000; i++) { set_numbers(i); delay(1000); } } ISR(TIMER2_COMPA_vect) { display_numbers(); }
今回はトランジスタを使わなくてもOKみたいです。もう少し電流が必要な場合はトランジスタやLEDドライバで電源を補う必要がありそうです。
この回路やスケッチで問題なさそうなので、近いうちにATmega328内部クロック単独で動かしたいと思います。その際ATmega328を7セグメントLEDの下に配置し小型軽量化を試みたいと思います。