・バー型10連LEDアレイをマイコンで制御する回路だ。I/Oポートには、LEDの他に圧電サウンダと可変抵抗器が接続されている。圧電サウンダは音を鳴らす他、ADコンバータから値を読み取れば、入力デバイスとして使うこともできる。可変抵抗器はADコンバータに接続されており、アナログ入力が可能だ。
・今回は、お約束のラーメンタイマ(10分まで可)と鼻息測定器(大声も可)のファームウェアを公開した。
マイコン ATMEL ATmega168P-20PU
オプトサプライ10バーLEDアレイ 3色(緑5黄3赤2)タイプ OSX10201-GYR1
圧電サウンダ(他励振) Murata PKM13EPYH4000-A0
カーボン抵抗器 150Ω x 10個、10kΩ、100kΩ
可変抵抗器 500kΩ
積層セラミックコンデンサ 0.1uF x 2個
ピンヘッダ 2x3
電池ボックス 単三型2本用
タクトスイッチ
ユニバーサル基板 70mm x 90mm
(動作)
可変抵抗器のつまみを右回りに回すと、設定時間が増え、設定時間数だけLEDが点灯する。ただし、最初のLEDだけは3秒に設定される。
タクトスイッチを押すと、LEDが点滅を開始する。1分経過するごとに右端からLEDが消灯していく。
このときタクトスイッチを押すと、カウントダウンを停止し、スリープモードに移行する。
タクトスイッチが押されずに設定した時間が経過すると、LEDがすべて点滅し、ブザーが鳴る。
ブザーが鳴っている間にスイッチを押すと、スリープモードに移行する。
スリープモードに入っている間にスイッチを押すと、最初の状態に戻る。
(ソースコード barled-mega168-timer.c)
// PD0 : LED-BAR 01 0:ON 1:OFF// PD1 : LED-BAR 02 0:ON 1:OFF// PD2 : LED-BAR 03 0:ON 1:OFF// PD3 : LED-BAR 04 0:ON 1:OFF// PD4 : LED-BAR 05 0:ON 1:OFF// PB6 : LED-BAR 06 0:ON 1:OFF// PB7 : LED-BAR 07 0:ON 1:OFF// PD5 : LED-BAR 08 0:ON 1:OFF// PD6 : LED-BAR 09 0:ON 1:OFF// PD7 : LED-BAR 10 0:ON 1:OFF// PC0(ADC0/PCINT8) : Switch 1:OFF 0:ON// PC1(ADC1) : Resister// PC2(ADC2) : Piezo Buz#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>void wait(volatile long i){while (i-- > 0);
}#define isSwOff() ( PINC & (1<<PC0) )#define buz() ( PORTC ^= (1<<PC2) )#define led01() PORTD ^= (1<<PD0)#define led02() PORTD ^= (1<<PD1)#define led03() PORTD ^= (1<<PD2)#define led04() PORTD ^= (1<<PD3)#define led05() PORTD ^= (1<<PD4)#define led06() PORTB ^= (1<<PB6)#define led07() PORTB ^= (1<<PB7)#define led08() PORTD ^= (1<<PD5)#define led09() PORTD ^= (1<<PD6)#define led10() PORTD ^= (1<<PD7)#define led01on() PORTD &= ~(1<<PD0)#define led02on() PORTD &= ~(1<<PD1)#define led03on() PORTD &= ~(1<<PD2)#define led04on() PORTD &= ~(1<<PD3)#define led05on() PORTD &= ~(1<<PD4)#define led06on() PORTB &= ~(1<<PB6)#define led07on() PORTB &= ~(1<<PB7)#define led08on() PORTD &= ~(1<<PD5)#define led09on() PORTD &= ~(1<<PD6)#define led10on() PORTD &= ~(1<<PD7)#define led01off() PORTD |= (1<<PD0)#define led02off() PORTD |= (1<<PD1)#define led03off() PORTD |= (1<<PD2)#define led04off() PORTD |= (1<<PD3)#define led05off() PORTD |= (1<<PD4)#define led06off() PORTB |= (1<<PB6)#define led07off() PORTB |= (1<<PB7)#define led08off() PORTD |= (1<<PD5)#define led09off() PORTD |= (1<<PD6)#define led10off() PORTD |= (1<<PD7)void led10bar(uint16_t bitvalue)// bitvalue : 0b 0abcdefg 0:OFF, 1:ON{ if (bitvalue & 0b1000000000) led10on(); else led10off(); if (bitvalue & 0b0100000000) led09on(); else led09off(); if (bitvalue & 0b0010000000) led08on(); else led08off(); if (bitvalue & 0b0001000000) led07on(); else led07off(); if (bitvalue & 0b0000100000) led06on(); else led06off(); if (bitvalue & 0b0000010000) led05on(); else led05off(); if (bitvalue & 0b0000001000) led04on(); else led04off(); if (bitvalue & 0b0000000100) led03on(); else led03off(); if (bitvalue & 0b0000000010) led02on(); else led02off(); if (bitvalue & 0b0000000001) led01on(); else led01off();}void led10barblink(uint16_t bitvalue)// bitvalue : 0b 0abcdefg 0:OFF, 1:ON{ if (bitvalue & 0b1000000000) led10(); if (bitvalue & 0b0100000000) led09(); if (bitvalue & 0b0010000000) led08(); if (bitvalue & 0b0001000000) led07(); if (bitvalue & 0b0000100000) led06(); if (bitvalue & 0b0000010000) led05(); if (bitvalue & 0b0000001000) led04(); if (bitvalue & 0b0000000100) led03(); if (bitvalue & 0b0000000010) led02(); if (bitvalue & 0b0000000001) led01();}void beep(int length, int pitch){ volatile unsigned int i, j; for ( i = 0; i < length; i++) { buz(); for (j = 0; j < pitch;j++); }}void initAdc(void){ // AD Conv. Enable & Clock ferquency and the input clock to the ADC) ADCSRA = ( (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0) );}uint8_t adc(uint8_t adcport){ uint8_t adcdata; // A/D Conv. data ADMUX = (1<<ADLAR) | adcport; // AD-Conv. 8-bit precision, Use ADC-PORTx ADCSRA |= (1<<ADIF); // Set ADC Interrupt flag ADCSRA |= (1<<ADSC); // Start AD Conv. while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adc adcdata = ADCH; // 8-bit precision return adcdata;}void initPCInt8(void){ PCICR |= (1<<PCIE1); // Pin change interrupt enable 0 (PCINT14..8) PCMSK1 |= (1<<PCINT8); // PCINT8 enable }#define StSetTime 0x01#define StCountdown 0x02#define StStop 0x03#define StSleep 0xffvolatile uint8_t STAGE = StSetTime; // Program STAGE definitionISR(PCINT1_vect){ if (isSwOff()) { switch(STAGE) { case StSetTime: STAGE = StCountdown; break; case StCountdown: STAGE = StSleep; break; case StStop: STAGE = StSleep; break; case StSleep: STAGE = StSetTime; break; default: STAGE = StSetTime; } }}void initInt0(void){ EIMSK |= (1<<INT0); // INT0 interrupt enable EICRA |= (1<<ISC01) | (0<<ISC00); // The falling edge ofINT0 or INT1}ISR(INT0_vect){}// Timer0void initTimer0(void){ TCCR0B |= (1<<CS01) | (1<<CS00); TCCR0B &= ~(1<<CS02);//Clock/64 TIMSK0 |= (1<<TOIE0); //Timer0 Overflow Interrupt Enable}volatile long TickCounter = 0;#define TC10min 36621L#define TC9min 32958L#define TC8min 29297L#define TC7min 25634L#define TC6min 21972L#define TC5min 18310L#define TC4min 14648L#define TC3min 10986L#define TC2min 7324L#define TC1min 3662L#define TC10sec 610L#define TC3sec 183LISR(TIMER0_OVF_vect){ TickCounter--;}#define VRADCPORT 0x01 // Trim Resister port no.int main(void){ uint8_t adcdata; unsigned int i; long tc; // Setting Time // Initialize I/O Port DDRD = (1<<PD7) | (1<<PD6) | (1<<PD5) | (1<<PD4) | (1<<PD3) | (1<<PD2) | (1<<PD1) | (1<<PD0); // LED BAR Output mode DDRB = (1<<PB6) | (1<<PB7); // LED BAR Output mode PORTC = (1<<PC0); // Pull up resister on PC0 (Switch) DDRC = (1<<PC2) ; // PC2 output mode Piezo Buzzer // Initailize Pin Change Interrupt initPCInt8(); // Initialize AD-convertor initAdc(); //Initialize Timer0 initTimer0(); // LED, Buz initialize for (i = 0; i < 3; i++) { led10bar(0b1111111111); beep(50, 5); wait(5000); led10bar(0b0000000000); wait(10000); } sei(); // Enable Interrupt STAGE = StSetTime; while (1) { switch (STAGE) { case StSetTime: // Set Time by Trim resistor adcdata = adc(VRADCPORT); if (adcdata > 0xd0) { led10bar(0b1111111111); tc = TC10min; } else if (adcdata > 0xce) { led10bar(0b1111111110); tc = TC9min; } else if (adcdata > 0xc2) { led10bar(0b1111111100); tc = TC8min; } else if (adcdata > 0xb1) { led10bar(0b1111111000); tc = TC7min; } else if (adcdata > 0xa7) { led10bar(0b1111110000); tc = TC6min; } else if (adcdata > 0x9c) { led10bar(0b1111100000); tc = TC5min; }else if (adcdata > 0x91) { led10bar(0b1111000000); tc = TC4min; } else if (adcdata > 0x55) { led10bar(0b1110000000); tc = TC3min; } else if (adcdata > 0x19) { led10bar(0b1100000000); tc = TC2min; } else { led10bar(0b1000000000); tc = TC3sec; } TickCounter = tc; break; case StCountdown: if (TickCounter > TC9min) { led10bar(0b1111111111); } else if (TickCounter > TC8min) { led10bar(0b1111111110); } else if (TickCounter > TC7min) { led10barblink(0b1111111100); } else if (TickCounter > TC6min) { led10bar(0b1111111000); } else if (TickCounter > TC5min) { led10bar(0b1111110000); } else if (TickCounter > TC4min) { led10bar(0b1111100000); } else if (TickCounter > TC3min) { led10bar(0b1111000000); } else if (TickCounter > TC2min) { led10bar(0b1110000000); } else if (TickCounter > TC3sec) { led10bar(0b1100000000); } else if (TickCounter > 0) { led10bar(0b1000000000); } else { STAGE = StStop; led10bar(0b0000000000); } wait(2500); led10bar(0b0000000000); wait(2500); break; case StStop: led10barblink(0b1111111111); beep(500, 5); wait(5000); break; case StSleep: led10bar(0b0000000000); set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); break; default: led10bar(0b0000000000); } } return 0;}
(Makefile)
# AVR-GCC MakefilePROJECT=barled-mega168-timerSOURCES=$(PROJECT).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).hex
clean:rm -f $(PROJECT).out
rm -f $(PROJECT).hex
鼻息測定器(barled-mega168-blow-meter)
(動作)
最初に3回LEDがすべて点滅し、音が鳴る。
次に、圧電サウンダに息を吹きかけると、その強さに応じていくつかのLEDが点滅し、音が鳴る。
鼻息ではなく、口笛や大声も検出できる。
タクトスイッチを押すとスリープモードに移行する。
スリープモード中にタクトスイッチを押すと最初に戻る。
(ソースコード barled-mega168-blow-meter.c)
// PD0 : LED-BAR 01 0:ON 1:OFF// PD1 : LED-BAR 02 0:ON 1:OFF// PD2 : LED-BAR 03 0:ON 1:OFF// PD3 : LED-BAR 04 0:ON 1:OFF// PD4 : LED-BAR 05 0:ON 1:OFF// PB6 : LED-BAR 06 0:ON 1:OFF// PB7 : LED-BAR 07 0:ON 1:OFF// PD5 : LED-BAR 08 0:ON 1:OFF// PD6 : LED-BAR 09 0:ON 1:OFF// PD7 : LED-BAR 10 0:ON 1:OFF// PC0(ADC0/PCINT8) : Switch 1:OFF 0:ON// PC1(ADC1) : Resister// PC2(ADC2) : Piezo Buz#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>void wait(volatile long i){while (i-- > 0);
}#define BuzOutputMode() ( DDRC = (1<<PC2) )#define BuzInputMode() ( DDRC &= ~(1<<PC2) )#define isSwOff() ( PINC & (1<<PC0) )#define buz() ( PORTC ^= (1<<PC2) )#define led01() PORTD ^= (1<<PD0)#define led02() PORTD ^= (1<<PD1)#define led03() PORTD ^= (1<<PD2)#define led04() PORTD ^= (1<<PD3)#define led05() PORTD ^= (1<<PD4)#define led06() PORTB ^= (1<<PB6)#define led07() PORTB ^= (1<<PB7)#define led08() PORTD ^= (1<<PD5)#define led09() PORTD ^= (1<<PD6)#define led10() PORTD ^= (1<<PD7)#define led01on() PORTD &= ~(1<<PD0)#define led02on() PORTD &= ~(1<<PD1)#define led03on() PORTD &= ~(1<<PD2)#define led04on() PORTD &= ~(1<<PD3)#define led05on() PORTD &= ~(1<<PD4)#define led06on() PORTB &= ~(1<<PB6)#define led07on() PORTB &= ~(1<<PB7)#define led08on() PORTD &= ~(1<<PD5)#define led09on() PORTD &= ~(1<<PD6)#define led10on() PORTD &= ~(1<<PD7)#define led01off() PORTD |= (1<<PD0)#define led02off() PORTD |= (1<<PD1)#define led03off() PORTD |= (1<<PD2)#define led04off() PORTD |= (1<<PD3)#define led05off() PORTD |= (1<<PD4)#define led06off() PORTB |= (1<<PB6)#define led07off() PORTB |= (1<<PB7)#define led08off() PORTD |= (1<<PD5)#define led09off() PORTD |= (1<<PD6)#define led10off() PORTD |= (1<<PD7)void led10bar(uint16_t bitvalue)// bitvalue : 0b 0abcdefg 0:OFF, 1:ON{ if (bitvalue & 0b1000000000) led10on(); else led10off(); if (bitvalue & 0b0100000000) led09on(); else led09off(); if (bitvalue & 0b0010000000) led08on(); else led08off(); if (bitvalue & 0b0001000000) led07on(); else led07off(); if (bitvalue & 0b0000100000) led06on(); else led06off(); if (bitvalue & 0b0000010000) led05on(); else led05off(); if (bitvalue & 0b0000001000) led04on(); else led04off(); if (bitvalue & 0b0000000100) led03on(); else led03off(); if (bitvalue & 0b0000000010) led02on(); else led02off(); if (bitvalue & 0b0000000001) led01on(); else led01off();}void led10barblink(uint16_t bitvalue)// bitvalue : 0b 0abcdefg 0:OFF, 1:ON{ if (bitvalue & 0b1000000000) led10(); if (bitvalue & 0b0100000000) led09(); if (bitvalue & 0b0010000000) led08(); if (bitvalue & 0b0001000000) led07(); if (bitvalue & 0b0000100000) led06(); if (bitvalue & 0b0000010000) led05(); if (bitvalue & 0b0000001000) led04(); if (bitvalue & 0b0000000100) led03(); if (bitvalue & 0b0000000010) led02(); if (bitvalue & 0b0000000001) led01();}void beep(int length, int pitch){ volatile unsigned int i, j; BuzOutputMode(); for ( i = 0; i < length; i++) { buz(); for (j = 0; j < pitch;j++); }}void initAdc(void){ // AD Conv. Enable & Clock ferquency and the input clock to the ADC) ADCSRA = ( (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0) );}uint8_t adc8(uint8_t adcport){ uint8_t adcdata; // A/D Conv. data ADMUX = (1<<ADLAR) | adcport; // AD-Conv. 8-bit precision, Use ADC-PORTx ADCSRA |= (1<<ADIF); // Set ADC Interrupt flag ADCSRA |= (1<<ADSC); // Start AD Conv. while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adc adcdata = ADCH; // 8-bit precision return adcdata;}uint16_t adc(uint8_t adcport){ uint16_t adcdata; // A/D Conv. data ADMUX = adcport; // AD-Conv. 10-bit precision ((0<<ADLAR)), Use ADC-PORTx ADCSRA |= (1<<ADIF); // Set ADC Interrupt flag ADCSRA |= (1<<ADSC); // Start AD Conv. while ( ( ADCSRA & (1<<ADIF) ) == 0); //Wait to complete adc adcdata = ADCL; // 10-bit precision adcdata |= (ADCH<<8); return adcdata;}void initPCInt8(void){ PCICR |= (1<<PCIE1); // Pin change interrupt enable 0 (PCINT14..8) PCMSK1 |= (1<<PCINT8); // PCINT8 enable }#define StStart 0x01#define StProc 0x02#define StStop 0x03#define StSleep 0xffvolatile uint8_t STAGE = StStart; // Program STAGE definitionISR(PCINT1_vect){ if (isSwOff()) { switch(STAGE) { case StStart: STAGE = StProc; break; case StProc: STAGE = StStop; break; case StStop: STAGE = StSleep; break; case StSleep: STAGE = StStart; break; default: STAGE = StSleep; } }}void initInt0(void){ EIMSK |= (1<<INT0); // INT0 interrupt enable EICRA |= (1<<ISC01) | (0<<ISC00); // The falling edge ofINT0 or INT1}ISR(INT0_vect){}// Timer0void initTimer0(void){ TCCR0B |= (1<<CS01) | (1<<CS00); TCCR0B &= ~(1<<CS02);//Clock/64 TIMSK0 |= (1<<TOIE0); //Timer0 Overflow Interrupt Enable}volatile long TickCounter = 0;#define TC10min 36621L#define TC9min 32958L#define TC8min 29297L#define TC7min 25634L#define TC6min 21972L#define TC5min 18310L#define TC4min 14648L#define TC3min 10986L#define TC2min 7324L#define TC1min 3662L#define TC10sec 610L#define TC3sec 183LISR(TIMER0_OVF_vect){ TickCounter--;}#define VRADCPORT 0x01 // Trim Resistor port no.#define BUZPORT 0x02 // Piezo Buzzer port no.int main(void){ uint16_t adcdata; uint16_t maxadcdata = 0; unsigned int i; // Initialize I/O Port DDRD = (1<<PD7) | (1<<PD6) | (1<<PD5) | (1<<PD4) | (1<<PD3) | (1<<PD2) | (1<<PD1) | (1<<PD0); // LED BAR Output mode DDRB = (1<<PB6) | (1<<PB7); // LED BAR Output mode PORTC = (1<<PC0); // Pull up resister on PC0 (Switch) // Buz Output BuzOutputMode(); // Initailize Pin Change Interrupt initPCInt8(); // Initialize AD-convertor initAdc(); //Initialize Timer0 initTimer0(); sei(); // Enable Interrupt STAGE = StStart; while (1) { switch (STAGE) { case StStart: // LED, Buz initialize for (i = 0; i < 3; i++) { led10bar(0b1111111111); beep(50, 5); wait(5000); led10bar(0b0000000000); wait(10000); } STAGE = StProc; maxadcdata = 0; i = 0; break; case StProc: // Get Analog signal by Piezo Buzzer BuzInputMode(); adcdata = adc(BUZPORT); if (adcdata > 0x04) { if (adcdata > maxadcdata) { maxadcdata = adcdata; } i++; } if (i > 4) { led10bar(maxadcdata); wait(5000); led10bar(0x000); STAGE = StStop; } break; case StStop: led10barblink(maxadcdata); beep(500, 5); wait(5000); break; case StSleep: led10bar(0b0000000000); set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); break; default: led10bar(0b0000000000); } } return 0;}
(Makefile)
# AVR-GCC MakefilePROJECT=barled-mega168-blow-meterSOURCES=$(PROJECT).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).hex
clean:rm -f $(PROJECT).out
rm -f $(PROJECT).hex