[BC19-02]LEDサイコロ
電子工作の定番、LEDを7個使った電子サイコロ
タクトスイッチや光センサでサイコロを振ることができる。
使用部品
使用部品
AVRマイコン Microchip (Atmel) AT tiny 26L / 861
LED 7個
フォトトランジスタ 新日本無線 NJL7502
圧電スピーカ(13mm) 村田製作所 PKM13EPYH4000-A0
タクトスイッチ 2ピン・ラジアルリード TVDT18-050CW-T
積層セラミックコンデンサ 0.1uF
カーボン抵抗器 150Ω 7個、100kΩ 1個
ブレッドボード EIC-801
バッテリースナップ
電池ボックス(単3形2本用、バッテリスナップタイプ)
ジャンパ線
回路図
回路図
実体配線図
実体配線図
プログラマとの接続
プログラマとの接続
ISPコネクタの1番をMISOとして、下図のように接続する。
ファームウェア
ファームウェア
ソースコード(AVR-GCC)
ソースコード(AVR-GCC)
/* 7-LED-DICE
* Traget : ATTINY26/861
*
* Input :
* ADC3(PA4) <PIN14> : A-D Convertor ( optical transistor ) Input : bright->Low V, dark->High V
* PB6(INT0) <PIN9> : Tact Switch 1:ON 0:OFF
* Output:
* PA0123 <PIN20,19,18,17> : LED1,2,3,4
* PB012 <PIN1,2,3> : LED5,6,7
* PA7 <PIN11> : Buzzer
*
* # LED layout
* PA0 PA1 PA2
* PA3
* PB0 PB1 PB2
*
*/
#include <avr/io.h>
#define led1_on() ( PORTA |= (1<<PA0) )
#define led2_on() ( PORTA |= (1<<PA1) )
#define led3_on() ( PORTA |= (1<<PA2) )
#define led4_on() ( PORTA |= (1<<PA3) )
#define led5_on() ( PORTB |= (1<<PB0) )
#define led6_on() ( PORTB |= (1<<PB1) )
#define led7_on() ( PORTB |= (1<<PB2) )
#define led1_off() ( PORTA &= ~(1<<PA0) )
#define led2_off() ( PORTA &= ~(1<<PA1) )
#define led3_off() ( PORTA &= ~(1<<PA2) )
#define led4_off() ( PORTA &= ~(1<<PA3) )
#define led5_off() ( PORTB &= ~(1<<PB0) )
#define led6_off() ( PORTB &= ~(1<<PB1) )
#define led7_off() ( PORTB &= ~(1<<PB2) )
#define led_b_on() ( PORTB |= 0b00000111 )
#define led_a_on() ( PORTA |= 0b00001111 )
#define led_b_off() ( PORTB &= ~0b00000111 )
#define led_a_off() ( PORTA &= ~0b00001111 )
#define buz() ( PORTA ^= (1<<PA7) )
#define is_switch() !( PINB & (1<<PB6) )
#define OFF 0x00
#define ON 0xff
#define TONE_LENGTH 100
#define PAUSE_LENGTH 5000
#define DARK_THRESHOLD 220
int adconv(void)
/* AD Convertor */
{
int adata;
/* Tiny26 */
ADCSR |= (1<<ADEN) | (1<<ADSC); // A-D convertor enable,
ADMUX = (1<<ADLAR) | (0b011); // Tyny26/861 : ADLAR=1, ADC3 SingleEndedInput
while ( !(ADCSR & (1<<ADIF)) ); // Tiny26
adata = ADCH;
ADCSR &=~(1<<ADIF); // Tiny26
/* Tiny 861
ADCSRA |= (1<<ADEN) | (1<<ADSC); // Tiny861 A-D convertor enable,
ADMUX = (1<<ADLAR) | (0b011); // Tyny26/861 : ADLAR=1, ADC3 SingleEndedInput
while ( !(ADCSRA & (1<<ADIF)) ); // Tiny861
adata = ADCH;
ADCSRA &=~(1<<ADIF); // Tiny861
*/
return adata;
}
uint8_t is_adc_switch(void)
// return value : bright -> dark : 0xff, else : 0x00
{
static uint8_t previous = 0x00; // Previous blightness 0xff: bright, 0x00:dark
int d;
uint8_t result;
d = adconv();
if (d > DARK_THRESHOLD) {
// dark
if (previous == 0xff) {
result = 0xff;
} else {
result = 0x00;
}
previous = 0x00;
} else {
// bright
result = 0x00;
previous = 0xff;
}
return result;
}
uint8_t is_dark(void)
// return value : dark : 0, bright : 0xff
{
int d;
d = adconv();
if (d > DARK_THRESHOLD) {
//dark
return 0xff;
} else {
return 0x00;
}
}
void wait(volatile int32_t i)
{
while (i-- > 0);
}
void init_io(void)
{
// Initialize I/O Port
PORTB |= (1<<PB6); // Pull up ON PB6 (switch)
DDRB &= ~(1<<PB6); // PB6 as input
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2);
DDRA &= ~(1<<PA4); // PA4 (ADC3) as input
DDRA |= (1<<PA0) | (1<<PA1) | (1<<PA2) | (1<<PA3) | (1<<PA7);
}
void tone(int16_t length)
{
int16_t i;
for (i = 0; i < length; i++) {
buz();
wait(8);
}
}
void dice1(void)
{
led4_on(); tone(TONE_LENGTH * 10); wait(PAUSE_LENGTH);
}
void dice2(void)
{
led1_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led7_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
}
void dice3(void)
{
led1_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led4_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led7_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
}
void dice4(void)
{
led1_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led3_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led5_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led7_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
}
void dice5(void)
{
led1_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led3_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led4_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led5_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led7_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
}
void dice6(void)
{
led1_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led2_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led3_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led5_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led6_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
led7_on(); tone(TONE_LENGTH); wait(PAUSE_LENGTH);
}
void dice_off()
{
led1_off();
led2_off();
led3_off();
led4_off();
led5_off();
led6_off();
led7_off();
}
int main(void)
{
init_io();
volatile uint8_t v = 0;
while(is_adc_switch() || is_switch());
dice_off();
while(1) {
if (is_adc_switch() || is_switch()) {
dice_off();
while(is_adc_switch() || is_switch() ) {
// ready
led_a_on();
wait(500);
led_b_on();
wait(500);
led_a_off();
wait(500);
led_b_off();
wait(500);
v++;
}
// dice
switch (v % 6){
case 0:
dice6();
break;
case 1:
dice1();
break;
case 2:
dice2();
break;
case 3:
dice3();
break;
case 4:
dice4();
break;
case 5:
dice5();
break;
default:
dice_off();
}
while ( !is_switch() && is_dark() ) {
v++;
}
} else {
v++;
}
}
return 0;
}
Makefile
Makefile
プログラマにはAVR ISP mkIIを使用する場合を示す。
ヒューズの設定は、内部クロック8MHz, 8分周(実質クロック1MHz)
AT tiny 26用
# AVR-GCC Makefile
PROJECT=dice-tiny26
SOURCES=$(PROJECT).c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=attiny26
TARGETDEV=t26
CFLAGS=-mmcu=$(MMCU) -Wall
$(PROJECT).hex: $(PROJECT).out
$(OBJCOPY) -j .text -O ihex $(PROJECT).out $(PROJECT).hex
$(PROJECT).out: $(SOURCES)
$(CC) $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program: $(PROJECT).hex
sudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex
clean:
rm -f $(PROJECT).out
rm -f $(PROJECT).hex
AT tiny861用
AT tiny861用
# AVR-GCC Makefile
PROJECT=dice-tiny26
SOURCES=$(PROJECT).c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=attiny861
TARGETDEV=t861
CFLAGS=-mmcu=$(MMCU) -Wall
$(PROJECT).hex: $(PROJECT).out
$(OBJCOPY) -j .text -O ihex $(PROJECT).out $(PROJECT).hex
$(PROJECT).out: $(SOURCES)
$(CC) $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program: $(PROJECT).hex
sudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex
clean:
rm -f $(PROJECT).out
rm -f $(PROJECT).hex