マイクから音が入力されると赤いLEDが光るようしたり、3つのマイクを用意し一番大きな音が入ってきたマイクの方向へ回転させるようなプログラムを実行してみます。


| 「マイクに大きな音が入ると赤のLEDが光る」プログラム |
|---|
// ファイル名 MicLED.c
// マイクに大きな音が入ると赤のLEDが光る
#include <htc.h>
__CONFIG(PWRTEN&HS&WDTDIS&UNPROTECT&MCLRDIS&BORDIS&IESODIS&FCMDIS);
#define _XTAL_FREQ 20000000
#define ANS7 0x80
typedef unsigned char byte;
void LED(byte n, byte times);
void Delay50();
void Delay100();
main()
{
int i;
int value, th = 16;
int average=128;
PORTA = 0; // PORTAを0にする
TRISA = 0; // PORTAを出力に設定する
ANSEL = ANS7; // アナログ入力をAN7をON
ADCON0 = 0x9d; // ADFM=1(右詰) AN7 adOn
OPTION = 0; // FOSC/4 プリスケーラ1/2
for(i=0; i<20; i++) // 電源電圧が安定するまで待つ
Delay100();
GODONE = 1; // A/D 変換開始
while(GODONE); // 変換完了
average = ADRESL; // 平均の初期値データを得る
while(1) {
GODONE = 1; // A/D 変換開始
while(GODONE); // 変換完了
value = ADRESL;
average = (average*9+value)/10;
if(value > average+th) LED(1, 1);
else if(value < average-th) LED(2, 1);
}
}
void LED(byte n, byte times)
{
byte i;
for(i=0; i<times; i++) {
PORTA = n;
Delay50(); // 50msディレイ
PORTA = 0;
Delay50(); // 50msディレイ
}
}
void Delay50() // 50m秒ディレイ
{
int i;
for(i=0; i<5; i++)
__delay_ms(10);
}
void Delay100() // 100m秒ディレイ
{
int i;
for(i=0; i<10; i++)
__delay_ms(10);
} |
void LED(byte n, byte times)
|
nで示されたLEDをtimesで指定された回数点滅させる。 n=1赤、n=2青、n=4緑 |
以下のプログラムをコピーして、貼り付けて使用してください。
| 「マイクに大きな音が入ると赤のLEDが光る(改良版)」プログラム |
|---|
// ファイル名 MicLED2.c
// マイクに大きな音が入ると赤のLEDが光る
// 改良版
#include <htc.h>
__CONFIG(PWRTEN&HS&WDTDIS&UNPROTECT&MCLRDIS&BORDIS&IESODIS&FCMDIS);
#define _XTAL_FREQ 20000000
#define ANS7 0x80
typedef unsigned char byte;
void LED(byte n, byte times);
void Delay50();
void Delay100();
main()
{
int i;
int value, th = 3;
int average=128;
int average2=0;
PORTA = 0; // PORTAを0にする
TRISA = 0; // PORTAを出力に設定する
ANSEL = ANS7; // アナログ入力をAN7をON
ADCON0 = 0x9d; // ADFM=1(右詰) AN7 adOn
OPTION = 0; // FOSC/4 プリスケーラ1/2
for(i=0; i<20; i++) // 電源電圧が安定するまで待つ
Delay100();
GODONE = 1; // A/D 変換開始
while(GODONE); // 変換完了
average = ADRESL; // 平均の初期値データを得る
while(1) {
GODONE = 1; // A/D 変換開始
while(GODONE); // 変換完了
value = ADRESL;
average = (average*9+value)/10;
if(value>average) average2 = (average2*11+value)/12;
if(average2 > average+th) {
LED(1, 1);
average2 = average;
}
}
}
void LED(byte n, byte times)
{
byte i;
for(i=0; i<times; i++) {
PORTA = n;
Delay50(); // 50msディレイ
PORTA = 0;
Delay50(); // 50msディレイ
}
}
void Delay50() // 50m秒ディレイ
{
int i;
for(i=0; i<5; i++)
__delay_ms(10);
}
void Delay100() // 100m秒ディレイ
{
int i;
for(i=0; i<10; i++)
__delay_ms(10);
}
|
if(value>average) average2 = (average2*11+value)/12; if(average2 > average+th) { LED(1, 1); average2 = average; } | 前のプログラムではマイク電圧が平均からどちらかにずれたらLEDが点灯しましたが、これは+に変化したときのみその平均を求め、そのずれた値の平均が元の平均よりずれた場合にLEDが点灯します。このようにすると、突発的なノイズを軽減することができます。 |
こちらも同様に次のプログラムも動かしてみます。
以下のプログラムをコピーして、貼り付けてください。
| 「3つのマイクで大きな音が入力された方向へ回転させる(MicLED3)」プログラム |
|---|
// ファイル名 MicLED3.c
// 3つのマイクのうち一番大きな音が入った方向に回転する
// 左:赤LED 右:緑LED 後:青LED
#include <htc.h>
__CONFIG(PWRTEN&HS&WDTDIS&UNPROTECT&MCLRDIS&BORDIS&IESODIS&FCMDIS);
#define _XTAL_FREQ 20000000
#define PERIOD 100
#define false 0
#define true 1
#define AN4 0x91
#define AN5 0x95
#define AN6 0x99
#define AN7 0x9d
#define AN10 0xa9
#define AN11 0xad
#define ABS(x) ((x>=0) ? (x) : -(x))
typedef unsigned char byte;
void LED(byte n, byte times);
void Delay50();
void Delay100();
void Mic();
void initialize();
// グローバル変数の宣言
byte counter=0;
byte LeftCdS, CenterCdS, RightCdS;
byte ADch=0;
byte ConvEndFlag;
byte ADC[4]={AN4,AN5,AN6,AN11};
// 割り込み処理ルーチン
void interrupt Intr(void)
{
// 約2ms毎に割り込む
if(T0IF) { // 割り込みがtimer0からか?
counter++;
TMR0 = PERIOD;
T0IF = 0; // 割り込みフラグクリア
return;
}
if(ADIF) { // 割り込みがADコンバーターからか?
if(ADch==0) LeftCdS = ADRESH;
else if(ADch==1) CenterCdS = ADRESH;
else if(ADch==2) RightCdS = ADRESH;
ConvEndFlag=true; // データの更新あり
ADIF = 0; // 割り込みフラグクリア
}
}
main()
{
int i;
initialize();
// Timer0 の設定
T0IE=1; // Timer0 の割り込みON
T0IF=0; // 割り込みフラグクリア
// ADコンバーターの設定
ADIE = 1; // ADコンバータの割り込み許可
ADIF = 0; // 割り込みフラグクリア
PEIE = 1; // 周辺装置の割り込み許可
GIE = 1; // CPUへの割り込み許可
GODONE = 1; // AD変換スタート
for(i=0; i<20; i++) // 電源電圧が安定するまで待つ
Delay100();
LED(5, 3); // 用意ができたら黄色LED点滅
Mic();
}
void initialize()
{
PORTA = 0; // PORTAを0にする
TRISA = 0; // PORTAを出力に設定する
TRISB = 0x30; // 4,5input
PORTB = 0;
PORTC = 0; // PORTCを0にする
TRISC = 0x0f; // PORTC下4bit入力、上4bit出力
ANSEL = 0xF0; // AN4,5,6,7 ON
ANSELH = 0x0C; // AN10,11 ON
ADCON0 = AN4; // ADFM=0(左) AN4 adOn
// 1 = Right justified
OPTION = 0;
// 1:8 prescale
T1CON = 0x31; // Timer1 settings
TMR1IF = 0; // clear TMR1IF
TMR1H = 0xf8; // Initialize Timer1 register
TMR1L = 0x00;
ADC[0]=AN4;
ADC[1]=AN5;
ADC[2]=AN6;
ADC[3]=AN11;
}
void LED(byte n, byte times)
{
byte i;
for(i=0; i<times; i++) {
PORTA = n;
Delay50(); // 50msディレイ
PORTA = 0;
Delay50(); // 50msディレイ
}
}
void Delay50() // 50m秒ディレイ
{
int i;
for(i=0; i<5; i++)
__delay_ms(10);
}
void Delay100() // 100m秒ディレイ
{
int i;
for(i=0; i<10; i++)
__delay_ms(10);
}
byte Leftspeed=208;
byte Centerspeed=208;
byte Rightspeed=208;
#define MICTH 5
#define MIDLOW 80
void Mic()
{
byte i;
int average[3]={185,185,185};
int x,diff[3];
byte a,b,c,max;
unsigned int cnt=0;
GIE=0;
ADC[0]=AN7;
ADC[1]=AN10;
ADC[2]=AN11;
for(cnt=0; cnt<1000; cnt++) {
for(i=0; i<3; i++) {
ADCON0 = ADC[i];
GODONE = 1;
while(GODONE);
x = ADRESL;
average[i] = (average[i]*9+x)/10;
}
}
while(RA3){ // スイッチが押されたら抜ける
for(i=0; i<3; i++) {
ADCON0 = ADC[i];
GODONE = 1;
while(GODONE);
x = ADRESL;
diff[i] = ABS(average[i] - x);
average[i] = (average[i]*9+x)/10;
}
if((diff[0] >MICTH) || (diff[1]>MICTH) || (diff[2]>MICTH)) {
a=diff[0]; b=diff[1]; c=diff[2];
if(a>b) {
if(a>c) { max=0; }
else { max=2;}
}
else if(b>c) { max = 1; }
else { max=2; }
GIE=1;
x=500; // 回転カウント
switch(max){
case 2: // Left
PORTA = 4;
Rightspeed = ~MIDLOW; Leftspeed = MIDLOW;
RC5=1; RC7=0;
break;
case 1: // backward
PORTA = 2;
if(diff[1]&1){ // たまに逆回りする
Rightspeed = ~MIDLOW; Leftspeed = MIDLOW;
RC5=1; RC7=0;
}
else {
Rightspeed = MIDLOW; Leftspeed = ~MIDLOW;
RC5=0; RC7=1;
}
x = 700;
break;
case 0: // Right
PORTA = 1;
Rightspeed = MIDLOW; Leftspeed = ~MIDLOW;
RC5=0; RC7=1;
break;
default:
PORTC &= 0x0f;
}
counter=0;
cnt=0;
while(cnt!=x) {
if(counter==0) cnt++;
RC4 = counter<Rightspeed;
RC6 = counter<Leftspeed;
if(!RA3) return;
}
PORTC &= 0x0f;
PORTA = 0;
GIE=0;
Delay100();
for(cnt=0; cnt<500; cnt++) {
for(i=0; i<3; i++) {
ADCON0 = ADC[i];
GODONE = 1;
while(GODONE);
x = ADRESL;
average[i] = (average[i]*9+x)/10;
}
}
} //if
}
GIE=1;
}
|