電子工作の定番、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として、下図のように接続する。
/* 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 220int 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;}プログラマにはAVR ISP mkIIを使用する場合を示す。
ヒューズの設定は、内部クロック8MHz, 8分周(実質クロック1MHz)
AT tiny 26用
# AVR-GCC MakefilePROJECT=dice-tiny26SOURCES=$(PROJECT).cCC=avr-gccOBJCOPY=avr-objcopyMMCU=attiny26TARGETDEV=t26CFLAGS=-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).hexclean: rm -f $(PROJECT).out rm -f $(PROJECT).hex# AVR-GCC MakefilePROJECT=dice-tiny26SOURCES=$(PROJECT).cCC=avr-gccOBJCOPY=avr-objcopyMMCU=attiny861TARGETDEV=t861CFLAGS=-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).hexclean: rm -f $(PROJECT).out rm -f $(PROJECT).hex