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の下に配置し小型軽量化を試みたいと思います。
