目次

心拍検知ユニット

概要

以前から興味があった「心拍“心臓の鼓動”」を検知するユニットを作成しました。
今回は、単純に心拍を検知し、LEDとブザーで知らせるだけのものにしました。
将来的には、LCDに心拍数を表示させてみようと思っています。

動作原理

赤外線リモコンに使われる赤外線LEDと赤外線受光素子を使った方法を採用しました。
赤血球に含まれるヘモグロビンは赤外線を吸光する性質があり、動脈の脈拍動に伴って赤外線吸光度が変化することを捕捉して心拍を計測するものです。

赤外線LEDと赤外線受光素子には、フォトインタラプタを採用しました。
以前にジャンク袋を購入したときに10個程入っていたものです。
型番は無記入なのでよく分かりません。

PICのソフトウエアでの処理は、割と単純です。
<旧版>
FETのドレイン電圧(無信号時には約3V)よりも、

で1波としてカウントし、LED,ブザーを制御します。
<改良版>
旧版は、基準電圧を絶対値の3Vとしましたが、精度を高めようとすると、電源電圧や2SK241のドレイン電圧、PICのA/D変換のリファレンス電圧そのものの精度を高めなければなりません。
それでは調整が面倒くさくなるので、基準電圧を相対値としました。

回路図

ソースコード

改良版のソースコード(絶対値比較から相対値比較へ変更しました。)

heartbeat2.c
//********************************************************************** 
 
void	Pwm_Change_DutyEx(unsigned int duty_ratio)
{
    CCPR1L = duty_ratio >> 2;
    CCP1CON.F6 = duty_ratio & 0b00000001;
    CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; 
}
 
//********************************************************************** 
// 1msec毎に10回A/D変換し、その平均値を返す。
// 10sec毎の平均値(1万回分)を求める。 
 
unsigned	int		ave, accCnt;
unsigned	long	acc;
 
unsigned	int	Adc_Read_Ex(unsigned short channel)
{
	unsigned	int		ad0, ad;
	unsigned	char	cnt;
	ad0 = 0;
	GPIO.F4 = 1;
	for (cnt = 0; cnt < 10; cnt++) {
		ad = Adc_Read(channel);
		ad0 += ad;
		// 平均値を求める。 
		acc += ad;
		accCnt++;
		if (accCnt == 10000) {
			ave = acc / 10000;
			accCnt = 0;
			acc = 0;
		}
		//
		Delay_us(1000);
	}
	GPIO.F4 = 0;
	return (ad0 / 10);
}
 
//********************************************************************** 
 
void	main()
{
	unsigned	int		ad0, old;
	unsigned	char	cnt;
	//
	OSCCON = 0b01110000;	// クロックは8Mhz 
	CMCON0 = 0b00000111;	// コンパレータは使用しない。 
	ANSEL = 0b00000001;		// A/D変換を使用する。
	TRISIO = 0b00000001;
	GPIO = 0b00001000;
	Pwm_Init(3000);		// 発振周波数は、3kHz
	Pwm_Change_DutyEx((PR2 * 4) / 2);	// デューティ比は、50% 
	Pwm_Stop();
	//
	acc = 0;
	accCnt = 0;
	ave = 3000 / 5;
	//
	while(1) {
		// 心拍の立ち下がりをチェックする。 
		cnt = 0;
		while(1) {
			ad0 = Adc_Read_Ex(0);
			if (ad0 > (ave + 20)) {	// 平均値+0.1V以上かをチェックする。 
				cnt++;
			} else {
				cnt = 0;
			}
			if (cnt > 5)	// 5回連続するかをチェックする。 
				break;
		}
		// ブザーを鳴らす。 
		Pwm_Start();
		GPIO.F1 = 1;
		Delay_ms(10);
		GPIO.F1 = 0;
		Pwm_Stop();
		// 心拍の立ち上がりをチェックする。 
		cnt = 0;
		while(1) {
			ad0 = Adc_Read_Ex(0);
			if (ad0 < (ave - 20)) {	// 平均値-0.1V以下かをチェックする。
				cnt++;
			} else {
				cnt = 0;
			}
			if (cnt > 5)	// 5回連続するかをチェックする。
				break;
		}
	}
}
 
//**********************************************************************

旧版のソースコード

heartbeat.c
//********************************************************************** 
 
void	Pwm_Change_DutyEx(unsigned int duty_ratio)
{
    CCPR1L = duty_ratio >> 2;
    CCP1CON.F6 = duty_ratio & 0b00000001;
    CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; 
}
 
//********************************************************************** 
// 10回A/D変換し、その平均値を返す。クロックが8Mhzの場合、約1msec要する。 
unsigned	int	Adc_Read_Ex(unsigned short channel)
{
	unsigned	int		ad0;
	unsigned	char	cnt;
	ad0 = 0;
	GPIO.F4 = 1;
	for (cnt = 0; cnt < 10; cnt++) {
		ad0 += Adc_Read(channel);
	}
	GPIO.F4 = 0;
	return (ad0 / 10);
}
 
//********************************************************************** 
 
void	main()
{
	unsigned	int		ad0, old;
	unsigned	char	cnt;
	//
	OSCCON = 0b01110000;	// クロックは8Mhz 
	CMCON0 = 0b00000111;	// コンパレータは使用しない。 
	ANSEL = 0b00000001;		// A/D変換を使用する。
	TRISIO = 0b00000001;
	GPIO = 0b00001000;
	Pwm_Init(3000);
	Pwm_Change_DutyEx((PR2 * 4) / 2);
	Pwm_Stop();
	while(1) {
		// 心拍の立ち下がりをチェックする。 
		cnt = 0;
		while(1) {
			ad0 = Adc_Read_Ex(0);
			if (ad0 > (3100 / 5)) {	// 3.1V以上かをチェックする。 
				cnt++;
			} else {
				cnt = 0;
			}
			if (cnt > 5)	// 5回連続するかをチェックする。 
				break;
		}
		// ブザーを鳴らす。 
		Pwm_Start();
		GPIO.F1 = 1;
		Delay_ms(10);
		GPIO.F1 = 0;
		Pwm_Stop();
		// 心拍の立ち上がりをチェックする。 
		cnt = 0;
		while(1) {
			ad0 = Adc_Read_Ex(0);
			if (ad0 < (2900 / 5)) {	// 2.9V以下かをチェックする。
				cnt++;
			} else {
				cnt = 0;
			}
			if (cnt > 5)	// 5回連続するかをチェックする。
				break;
		}
	}
}
 
//**********************************************************************

動作確認

使用したフォトインタラプタです。
発光部と受光部が向かい合わせなので、ニッパーで切り離して使用します。

全体の回路です。右側の黒い部品がフォトインタラプタです。
この上に指をのせるだけです。心拍に合わせて左下のミニスピーカとLEDを制御します。

フォトインタラプタの下側が赤外線の発光部です。目には見えませんがデジカメには写りますね。

デジタルオシロで波形を観測しました。アナログオシロでは遅すぎてデジカメで写すことが出来ません。
レンジは、1v/DIV、1sec/DIVです。2SK241のドレイン電圧が無信号時には約3Vです。

ドレインの波形(つまり心拍の波形)とLEDの波形(つまり検知した波形)です。

如何ですか?
自分の心拍を常時計測し健康維持に役立てることが出来ないものでしょうか? ^_^

著作権表示 copyright notice

このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。詳細
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.Details