ATMEGA168で光センサブザーLEDマーカ

mega168pでA/Dコンバータ対応LEDブザーマーカ

前回、ATTINY26Lを使って、フォトトランジスタに手をかざすなどして、光センサへの入力を変えてやると、それに応じて音やLEDの点滅間隔が変化する回路を作った。

残念ながらATTINT26Lは製造中止の部品なので、入手しやすいATMEGA168Pでも作ってみた。

部品リスト

ファームウェア (その1)

ATTINY26版と同様の動きをする。けっこう面白い。

// Mega168 A/D Convertor Test / Opt-transistor-Buz-LED-Marker
// AVR Device : ATmega168
// OC1B(PB2) : Buz
// PB0 : LED 1:ON, 0:OFF
// ADC0(PIN23)
#include <avr/io.h>
#define led_on() PORTB |= (1<<PB0)
#define led_off() PORTB &= ~(1<<PB0)
#define buz_on() PORTB |= (1<<PB2)
#define buz_off() PORTB &= ~(1<<PB2)
void wait(volatile long i)
{
while(i-- > 0);
}
void init_adc(void)
{
// AD Conv. Enable & Clock ferquency and the input clock to the ADC)
ADCSRA = ( (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0) );
}
unsigned int get_ad(char adcport)
// arg: adcport : 0 -
{
ADMUX = adcport; // AD-Conv. PORT Setup
ADCSRA |= (1<<ADIF); // Set ADC Interrupt flag
ADCSRA |= (1<<ADSC); // Start AD Conv.
while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adc
return ADCW;
}
int main(void)
{
volatile long i;
unsigned int s; // ADC input signal
init_adc(); // ADC port initialize
// PORTB2,0 を出力モード
DDRB = (1<<PB2) | (1<<PB0);
while(1) {
s = get_ad(0x00);
led_on();
for ( i = 0; i < (s>>3); i++) {
buz_on(); wait(s>>2);
buz_off(); wait(s>>2);
}
led_off(); wait(s<<5);
}
return 0;
}

ファームウェア(その2)

※OC1B出力を利用して、周波数を可変

// Mega168 A/D Convertor Test / Opt-transistor-Buz-LED-Marker
// AVR Device : ATmega168
// OC1B(PB2) : Buz
// PB0 : LED 1:ON, 0:OFF
// ADC0(PIN23)
#include <avr/io.h>
#define led_on() PORTB |= (1<<PB0)
#define led_off() PORTB &= ~(1<<PB0)
#define buz_on() PORTB |= (1<<PB2)
#define buz_off() PORTB &= ~(1<<PB2)
void wait(volatile long i)
{
while(i-- > 0);
}
void init_timer1_ctc(void)
// Timer/Counter1 を CTC (Clear Timer on Compare mode)モードで初期化
{
TCCR1A = (0<<WGM11) | (0<<WGM10) | (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (1<<COM1B0);
TCCR1B = (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
OCR1A = 0x0000; OCR1B = 0x0000; // OCR1A = 0x0001 で最高周波数、 OCR1A = 0xffff で最低周波数
}
void init_adc(void)
{
// AD Conv. Enable & Clock ferquency and the input clock to the ADC)
ADCSRA = ( (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0) );
}
unsigned int get_ad(char adcport)
// arg: adcport : 0 -
{
ADMUX = adcport; // AD-Conv. PORT Setup
ADCSRA |= (1<<ADIF); // Set ADC Interrupt flag
ADCSRA |= (1<<ADSC); // Start AD Conv.
while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adc
return ADCW;
}
int main(void)
{
volatile long i;
unsigned int s; // ADC input signal
init_timer1_ctc(); /* タイマ1を CTC モードで初期化 */
init_adc(); // ADC port initialize
// PORTB2,0 を出力モード
DDRB = (1<<PB2) | (1<<PB0);
while(1) {
s = get_ad(0x00);
led_on();
OCR1A = s;
wait(s * 16);
led_off();
OCR1A = 0;
wait(s * 16);
}
return 0;
}

参考(AVR-GCC用Makefile)

# AVR-GCC Makefile
PROJECT=mega168adc
SOURCES=mega168adc.c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=atmega168
TARGETDEV=m168P
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

回路図

回路図

※ブレッドボードで製作する場合には、JP3のISP端子は省略。

※実験用の回路なので、VCCやAVCCに接続すべきコンデンサやコイルを省略してある。