・ロウソクのように、息を吹きかけると消える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 1000
ISR(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 Makefile
PROJECT=anacmp-2313
SOURCES=$(PROJECT).c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=attiny2313
TARGETDEV=t2313
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