・ロウソクのように、息を吹きかけると消えるLEDライトを作ってみた。
・圧電スピーカに振動を与えると、わずかだが電圧が発生する。その電圧をマイコンのアナログコンパレータで検出すると、LEDが消える。
・ファームウェアRev.1では、本当のロウソクと違って、もう一度息を吹きかけると点灯してしまう。もっとも、この動作はプログラムでどうにでもなるわけだが。
・そこで、ファームウェアRev.2では、1回吹いただけでは点灯しないように変更。1秒程度の間隔をあけてセンサを2回たたくと点灯する。効果音も追加してみた。
ミニブレッドボード BB-601
AVRマイコン ATTINY2313-20PU またはATTINY2313V-10PU
5mm径LED
圧電スピーカ (13mm)PKM13EPYH4000-A0
カーボン抵抗器 150Ω、1/4W 2個
カーボン抵抗器 100kΩ、1/4W
カーボン抵抗器 10kΩ、1/4W
バッテリースナップ
単3電池2本用電池ボックス
ジャンパ線1本
(Rev.2 吹くと音が鳴って点滅しながら消灯、約1秒間隔で2回たたくと、音がなり、点滅しながら点灯する。)
// Analog Cmparator Application ( Blow Out LED )// TARGET : ATTINY2313 (Internal OSC : 8MHz / 8 ( Factory default ) // AIN1 : Resistor// AIN0 ( PB0 ) : Piezo speaker// PB3 : LED (0:ON, 1:OFF)#include <avr/io.h>#include <avr/interrupt.h>#define led_off() ( PORTB |= (1<<PB3) )
#define led_on() ( PORTB &= ~(1<<PB3) )
#define led() ( PORTB ^= (1<<PB3) )
#define buz() ( PORTB ^= (1<<PB0) )
#define is_analog_in() ( ACSR & (1<<ACO) ) // Analog Comparator Output
void wait(volatile long i)
{while (i-- > 0);
}void init_timer0(void){ //Set Timer Counter Control Register A (TCCR0A)// (WGM02) WGM01 WGM00
// ( 0 ) 0 0 // Normal mode
// ( 0 ) 1 1 // Fast PWM mode
// ( 0 ) 1 0 // CTC mode
// ( 1 ) 1 1 // Fast PWM mode TOP is OCR0A
// ( 1 ) 0 1 // PWM Phase correct TOP is OCR0A
// COM0A1 COM0A0 COM0B1 COM0B0
// 0 0 0 0 // Normal Port Operation, OC0A Disconnected.// 1 0 1 0 // Clear OC0A on Compare Match, set OC0A at TOP
TCCR0A = (0<<WGM02) | (0<<WGM00) | (0<<WGM00) | (0<<COM0A0) | (0<<COM0A1) | (0<<COM0B0) | (0<<COM0B1); // Normal mode, OC0A/B no output //Set Timer Counter Control Register B (TCCR0B)
// FOC0A FOC0B
// 0 0 ... TCCR0A, TCCR0B is written.
// CS02 CS01 CS00
// 0 0 1 ... No prescaling
// 0 1 0 ... clki/o / 8
// 0 1 1 ... clki/o / 64
// 1 0 0 ... clki/o / 256
// 1 0 1 ... clki/o / 1024
TCCR0B = (0<<CS02) | (1<<CS01) | (0<<CS00) ; // Clock Prescale : Clki/o / 8 // 1 interrrupt = 2.048ms TIMSK |= (1<<TOIE0); // TIMER0 interrupt enable}volatile unsigned long TCOUNTER = 0; // Timer 0 Counter
#define TC500MS 25#define TC2S 1000ISR(TIMER0_OVF_vect){ TCOUNTER++;}void waitms(volatile unsigned long t)
// Pause Execution about t[ms]{ volatile unsigned long limit;
limit = t / 2; TCOUNTER = 0; while (TCOUNTER < limit);}enum LED {ON, OFF};enum BOOLEAN {FALSE, TRUE};int main(void){int i, j;
unsigned int flag_light, flag_analog_in;
// Initialize I/O Port
DDRB = (1<<PB3) | (1<<PB0); // PB0: Output mode
// Initialize TIMER0
init_timer0(); //Enable Interrupt sei(); for (i = 0; i < 3; i++) {
led_on(); waitms(100);
for ( j = 0; j < 500; j++) { buz(); wait(5); }
led_off(); waitms(100);
}
DDRB &= ~(1<<PB0); // PB0: Input mode
led_on(); flag_light = ON;
while (1) {
switch (flag_light) { case OFF: // Light OFF -> ON // When Input Signal is H->L->H, LED light on. if (is_analog_in()) { waitms(500); flag_analog_in = FALSE; TCOUNTER = 0; while (TCOUNTER < TC500MS) { if (is_analog_in()) { flag_analog_in = TRUE; break; } } if (flag_analog_in == FALSE) { TCOUNTER = 0; while (TCOUNTER < TC2S) { if (is_analog_in()) { for (i = 150; i > 0; i--) {buz(); led(); wait(i); } led_on(); flag_light = ON; waitms(1000); break; } } } } break; case ON: // Light ON -> OFF // When Input Signal is detected, LED light on. if (is_analog_in()) { for (j = 1; j < 5; j++) { for (i = j * 100; i > 0; i--) { buz(); wait(5); } led(); } led_off(); flag_light = OFF; waitms(1000); } break; default : led_off(); flag_light = OFF; }}
return 0;
}(Rev.1 単純に吹いたとき消灯、次に吹くと点灯)
// Analog comparator test// TARGET : ATTINY2313// AIN1 : Resistor// AIN0 ( PB0 ) : Piezo speaker// PB3 : LED (0:ON, 1:OFF)#include <avr/io.h>#define led_off() ( PORTB |= (1<<PB3) )
#define led_on() ( PORTB &= ~(1<<PB3) )
#define led() ( PINB |= (1<<PB3) )
#define buz() ( PINB |= (1<<PB0) )
#define is_analog_in() ( ACSR & (1<<ACO) ) // Analog Comparator Output
void wait(volatile long i){while (i-- > 0);
}int main(void){int i, j;
// Initialize I/O Port
DDRB = (1<<PB3) | (1<<PB0); // PB0: Output mode
for (i = 0; i < 3; i++) {
led_on(); wait(5000);
for ( j = 0; j < 1000; j++) { buz(); wait(10); }
led_off(); wait(5000);
}
DDRB &= ~(1<<PB0); // PB0: Input mode
led_on();
while (1) {
if (is_analog_in()) {
led();
wait(10000);
}
}
return 0;
}# AVR-GCC MakefilePROJECT=anacmp-2313SOURCES=$(PROJECT).cCC=avr-gccOBJCOPY=avr-objcopyMMCU=attiny2313TARGETDEV=t2313CFLAGS=-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).hexsudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex
clean:rm -f $(PROJECT).out
rm -f $(PROJECT).hex