前回、ATTINY26Lを使って、フォトトランジスタに手をかざすなどして、光センサへの入力を変えてやると、それに応じて音やLEDの点滅間隔が変化する回路を作った。
残念ながらATTINT26Lは製造中止の部品なので、入手しやすいATMEGA168Pでも作ってみた。
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 SetupADCSRA |= (1<<ADIF); // Set ADC Interrupt flagADCSRA |= (1<<ADSC); // Start AD Conv.while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adcreturn ADCW;}int main(void){volatile long i;unsigned int s; // ADC input signalinit_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;}※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 SetupADCSRA |= (1<<ADIF); // Set ADC Interrupt flagADCSRA |= (1<<ADSC); // Start AD Conv.while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adcreturn ADCW;}int main(void){volatile long i;unsigned int s; // ADC input signalinit_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 MakefilePROJECT=mega168adcSOURCES=mega168adc.cCC=avr-gccOBJCOPY=avr-objcopyMMCU=atmega168TARGETDEV=m168PCFLAGS=-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).hexclean:rm -f $(PROJECT).outrm -f $(PROJECT).hex回路図
※ブレッドボードで製作する場合には、JP3のISP端子は省略。
※実験用の回路なので、VCCやAVCCに接続すべきコンデンサやコイルを省略してある。