概要
Arduino Unoと2桁7セグメントLEDを使い、0~99までカウントする装置の作り方を説明する。カウントアップ、カウントダウン、リセット機能を備えている。また、さらなる小型化を目指すため、ArduinoからAVRマイコンへ移植した。
実際は...
アミューズメント会社からUFOキャッチャーで景品を取るごとに景品獲得数をカウントする装置を作って欲しいという案件があった。完成し、連絡したが返事が来ない。結局、案件はなかったことに。大切な時間をかけて作ったカウンターを無駄にしたくないのでelchikaに投稿することにした。
Markdownを使うのは初めてであり、elchikaに記事を書くのも初めてである。
材料
- Arduino Uno
- AVRマイコン(ATtiny2313)
- AVRライター(AVRWRT3)
- 電源 (単三電池2本)
- 2桁7セグメントLEDアノードコモン
- タクトスイッチ 3つ
- 抵抗330Ω 10個
材料について
・電池ではなくブレッドボード用電源モジュールでもいい
・AVRライターは何でもいい(多分)
使用ソフト
- Arduino IDE
- Microchip Studio
- AVRWRT(デジットホームページより)
Microchip Studioについて
・12月頃にAtmel StudioからMicroship Studioへ名称が変更した。
2桁7セグメントLEDのピン配置
7セグの種類
カソードコモンでもいいが多少プログラムの書き換えが必要
配線
ソースコード
Arduino_conter.ino
//a : 13
//b : 11
//g : 10
//f : 9
//d : 8
//e : 6
//dp : 5
//c : 4
//A1 :12
//A2 :7
// LEDをオン・オフする際の出力
#define DIGIT_ON LOW
#define DIGIT_OFF HIGH
#define SEGMENT_ON HIGH
#define SEGMENT_OFF LOW
const int up_button = 19; //カウントアップボタン
const int down_button = 18; //カウントダウンボタン
const int reset_button = 17; //リセットボタン
//チャタリング防止用変数
int old_val1 = 1;
int old_val2 = 1;
int old_val3 = 1;
int up = 0;
int down = 0;
int reset = 0;
int i = 0;
const int digitPins[] = {5,4}; // ディジット(アノード)に接続するArduinoのピン
const int segmentPins[] = {13,12,11,10,9,8,7,}; // セグメントに接続するArduinoのピン
const int numberOfDigitPins = sizeof(digitPins) / sizeof(digitPins[0]); // ディジットの数
const int numberOfSegmentPins = sizeof(segmentPins) / sizeof(segmentPins[0]); // セグメントの数
// 数字と表示させるセグメントの関係
const int digits[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00100111, // 7
0b01111111, // 8
0b01101111, // 9
};
// 数字を表示する
void displayNumber(int n) {
// digits[n]の各ビットを調べて対応するセグメントを点灯・消灯する
for (int i = 0; i < numberOfSegmentPins; i++) {
digitalWrite(segmentPins[i], digits[n] & (1 << i) ? SEGMENT_OFF : SEGMENT_ON);
}
}
// セグメントをすべてオフにする
void clearSegments() {
for (int j = 0; j < numberOfSegmentPins; j++) {
digitalWrite(segmentPins[j], SEGMENT_OFF);
}
}
// 4桁の数字を表示する
void displayNumbers(int n) {
for (int i = 0; i < numberOfDigitPins; i++) { // 右の桁からディジットを選択する
digitalWrite(digitPins[i], DIGIT_ON); // ディジットをオンにする
displayNumber(n % 10); // 10で割った余りを求めて、1の位を求め、表示する
delay(12); // 12ms停止
clearSegments(); // セグメントをすべてオフにする
digitalWrite(digitPins[i], DIGIT_OFF); // ディジットをオフにする
n /= 10; // 10で割り、次に表示する数字を、1の位に移す
}
}
// setup() は,最初に一度だけ実行される
void setup() {
pinMode(up_button, INPUT_PULLUP );
pinMode(down_button, INPUT_PULLUP );
pinMode(reset_button, INPUT_PULLUP );
for (int i = 0; i < numberOfDigitPins; i++) {
pinMode(digitPins[i], OUTPUT); // digitPinsを出力モードに設定する
digitalWrite(digitPins[i], DIGIT_OFF);
}
for (int i = 0; i < numberOfSegmentPins; i++) {
pinMode(segmentPins[i], OUTPUT); // segmentPinsを出力モードに設定する
}
Serial.begin( 9600 );
}
//loop() は繰り返し実行される
void loop() {
up = digitalRead(up_button);
down = digitalRead(down_button);
reset = digitalRead(reset_button);
//以下チャタリング防止のプラグラム
if((up == 0) && (old_val1 == 1)){
if(i == 99){
i = 0;
} else{
i++;
}
}else if((i != 0) && (down == 0) &&(old_val2 == 1)){
i--;
}else if((reset == 0) &&(old_val3 == 1)){
i = 0;
}
displayNumbers(i);
old_val1 = up;
old_val2 = down;
old_val3 = reset;
}
AVR版
今思うと PICマイコンでもよかったが、家にAVRライターが転がってたのでAVRマイコンを使用することにした。しかし、ネット・書籍とも情報が少なくArduinoからAVRへの移行に苦戦した。簡単なやり方がありらしいが、今回はゼロから書くことにした。
ATtiny2313のピン配置
配線
ソースコード
avr_counter
/* PINS No.
a :PD0
b :PD1
c :PD2
d :PD3
e :PD4
f :PD5
g :PD6
A1 :PB0
A2 :PB1
up_btn :PB2
down_btn :PB3
rst_btn :PB4
*/
#include <avr/io.h>
#include <util/delay.h>
//チャタリング防止用変数
int old_val1 = 1;
int old_val2 = 1;
int old_val3 = 1;
int up = 0;
int down = 0;
int reset = 0;
int i = -1;
const int digitPins[] = {
0b00000010, //1桁目
0b00000001, //2桁目
};
const int digits[] = {
0b11000000, //0
0b11111001, //1
0b10100100, //2
0b10110000, //3
0b10011001, //4
0b10010010, //5
0b10000010, //6
0b11011000, //7
0b10000000, //8
0b10010000, //9
};
// 2桁の数字を表示する
void displayNumbers(int n) {
for (int i = 0; i < 2; i++) { // 右の桁からディジットを選択する
PORTB = digitPins[i]; // ディジットをオンにする
PORTD = digits[n % 10]; // 10で割った余りを求めて、1の位を求め、表示する
_delay_ms(12); // 12ms停止
PORTD = 0b00000000; // セグメントをすべてオフにする
PORTB = 0b00000000; // ディジットをオフにする
n /= 10; // 10で割り、次に表示する数字を、1の位に移す
}
}
int main(void)
{
DDRD = 0b11111111; //PIN D
DDRB = 0b00000011; //PIN B
PORTD = 0b11111111;
//ループ
while(1){
if((PINB&0b00000100)==0b00000000){ //UPボタン
up = 1;
}else{
up = 0;
}
if((PINB&0b00001000)==0b00000000){ //DOWNボタン
down = 1;
}else{
down = 0;
}
if((PINB&0b00010000)==0b00000000){ //RESETボタン
reset = 1;
}else{
reset = 0;
}
if((up == 0) && (old_val1 == 1)){
if(i == 99){
i = 0;
} else{
i++;
}
}else if((i != 0) && (down == 0) &&(old_val2 == 1)){
i--;
}else if((reset == 0) &&(old_val3 == 1)){
i = 0;
}
displayNumbers(i); //数字iを表示
old_val1 = up;
old_val2 = down;
old_val3 = reset;
}
return 0;
}
##動作映像
今後
オープンソースPCB-CAD 【Kicad】を使って、回路設計までできた。今後、中国の基盤発注業者【Electrow】に基盤の発注を注文をしようかと思う。それについての記事も書こうかな?
感想
Fritzingを使うのも初めてなので、回路図がとても汚い...
製作にあたってわからないことがあればコメントください。
投稿者の人気記事
-
Carlos
さんが
2021/02/26
に
編集
をしました。
(メッセージ: 初版)
-
Carlos
さんが
2021/02/26
に
編集
をしました。
Opening
yyy
2021/10/23
Carlos
2021/11/17 -
Carlos
さんが
2021/12/09
に
編集
をしました。
ログインしてコメントを投稿するコメント失礼いたします。arduino版の実際に組んだ回路図を見せていただけないでしょうか。自分が組んだところ上手く作動しなくて困っています。
返事が遅れてすみません、回路は解体してしまいました。
配線図のとおりに組んでもらうと動くはずですが...