FrontPage

2013/03/09からのアクセス回数 3936

温度センサーLM35を使う

今回も大野さんの本のお復習いをしています。

温度センサー LM35DZのデータシート を見るとLM35Dは、

  • 動作温度範囲は、0℃から100℃
  • 温度係数はリニアで+10.0mV/℃

と記載されています。 リニアーに10.0mV/℃なら50℃では、0.5Vが観測されるはずです。

例題13では、LM35DZの測定範囲の半分(50℃)でPSoCのBandGap1.3VになるようにPGAの倍率を 計算しています。

0.5V x 2.667 = 1.3335V

ADCINC(12bit)が以下のようにセットすると50℃では、1.3335 x 2047/1.3 = 2100となります。

  • 入力0Vで、0
  • 入力1.3Vで、2047
  • 入力2.6Vで、4095

ブレッドボードの組み立て

図8-66を参考にブレッドボードを組み立てます。

fig8_86.png

LM35には、P0[5]からREFHI(2.6V)を供給し、REFHIを測定するために、RefMuxを使ってP0[2]に出力しています。

L8_13_Breadboad.png

ポート番号とピンの対応は、以下の図を参考にしてください。

pin_layout.png

ユーザモジュールの配置

以下のユーザモジュールを配置します。

  • PGA
  • ADCINC
  • RefMux
  • LCD

L8_13_ABlock.png

ADCINC_1の設定は以下の様になっています。DataFormat: unsigned, Resolution: 12bitです。

L8_13_ADCINC_1.png

PGA_1の設定は、Gainを2.667, InputをAnalogColumn_InputMux_0にセットし、P0[5]と接続しています。

L8_13_PGA_1.png

RefMux_1の設定は、REFHIをセットし、出力をP0[2]に接続します。

L8_13_RefMux_1.png

ピンの設定では、P0[5]をStrongで初期値を1にセットするのがポイントです。 *1

L8_13_pinout.png

main.c

main.cはそのまま大野さんのプログラムを拝借しました。

#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules


char	strg[] = "ONDO 00.0  ";

int	read_adc(void)
{
	int	ival;

	ADCINC_1_GetSamples(1);
	while(ADCINC_1_fIsDataAvailable()==0);
	ival=ADCINC_1_iClearFlagGetData();
	return ival;
}

char	htoc(int ch)
{
	return "0123456789ABCDEF"[ch & 0xf];
}

void main(void)
{
	int		ival;
	long	lval;
	
	ADCINC_1_Start(ADCINC_1_HIGHPOWER);
	PGA_1_Start(PGA_1_HIGHPOWER);
	RefMux_1_Start(RefMux_1_HIGHPOWER);	// リファレンス実測のためアナログバスに出しておく

	M8C_EnableGInt;

	LCD_1_Start();
	strg[4] = 0x7e;			// 1行5文字目に'→'表示
	strg[9] = 0xdf;			// 1行9文字目に'゜'を表示
	strg[10] = 0x43;		// 1行10文字目に'C'を表示
	LCD_1_Position(1,0);	// 2行目にA/D変換値を表示するための準備
	LCD_1_PrCString("A/D read 0000(h)");	// Const文字列表示はPrCStringを使う
	
	for(;;) {
PRT0DR |= 0x40;		// モニタ
		ival = read_adc();
		LCD_1_Position(1,9);		// A/D変換値を16進で2行目に表示
		LCD_1_PrHexInt(ival);

		lval = ival;
		lval = lval * 3946L;		// リファレンス実測値(2.570V)とPGAゲイン(×2.667)の差を微修正

		lval = lval >> 12;
		lval *= 1000;				// 100℃/4095を0.1℃分解能の整数に換算
		lval = lval >> 12;
		ival = lval & 0xfff;

		strg[5] = htoc(ival / 100);	// 10進3桁の文字列に変換
		ival %= 100;
		strg[6] = htoc(ival / 10);
		ival %= 10;
		strg[8] = htoc(ival);
		strg[11] = '\0';			// 念のための文字列終端コード
		LCD_1_Position(0,0);
		LCD_1_PrString(strg);		// RAM文字列表示はPrStringを使う
PRT0DR &= ~0x40;		// モニタ
	}
}

動かしてみる

早速動かしてみましょう。

L8_13_run.png

リファレンスの実測値は、2.6Vではなく2.570Vでした。

Raspberry Piと接続

Raspberry Piと接続するためにI2CスレーブをPSocのブレッドボードに追加します。

ユーザモジュールEzI2Csを配置します。

EzI2Csの設定は、I2Cのアドレスには0x20(32)をセットし、以下の様にしました。

L8_13_EzI2Cs_1.png

EzI2Csを使うことによってI2Cマスターからは、PSoCがEEPROMと同じように扱うことができます。

テストのために、EzI2Cs用のバッファを以下のように定義します。 msgは、LCDの3段目に出力する文字列で、ivalはLM35から読み取った値をリードオンリーとします。

// EzI2Cs用のバッファ
struct I2C_Regs {
	char	msg[8];
	int		ival;	// LM35 temp read only to I2C
} myI2C_regs = {
	"1234567",
	0
};

EzI2Csを追加したことによるmain関数の変更は、変数宣言直後の以下の部分と

	M8C_EnableGInt;
	
	EzI2Cs_1_SetRamBuffer(sizeof(myI2C_regs), 8, (BYTE *)&myI2C_regs);
	EzI2Cs_1_Start();

forループの最初にivalの値をmyI2C_reg.ivalにコピーする以下の部分です。

		ival = read_adc();
		myI2C_regs.ival = ival;		// ivalをI2C用レジスターバッファにセット

Raspberry Piとの接続

PSoCとRasperry Piとの接続は、以下の様にします。

  • GND: PI-02 3ピンをPSoCのGNDに接続
  • SDA: PI-01 2ピンをPSoCのP1[5]に接続
  • SLC: PI-01 3ピンをPSoCのP1[7]に接続

L8_13_I2Cs.png

実行結果

さっそくRaspberry PiのI2C Toolを使って動作を確認してみましょう。

最初にPSoCのI2Cスレーブを認識するところから、i2cdetectを使ってデバイスをスキャンします。 無事0x20が検出できています。

$ sudo i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

次に"H"をPSoCに送ってみます。*2

$ sudo i2cset -y 0 0x20 0x00 0x48 # H
$ sudo i2cset -y 0 0x20 0x00 

最終目的の温度を読み取ると、

$ sudo i2cget -y 0 0x20 0x08 w
0x1a04

バイトが入れ替わっているので、正しい値は0x041aが正常に受け取れていることが確認できました。

コメント

選択肢 投票
おもしろかった 7  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。


(Input image string)


*1 これに気づかずに動かなくて手こずりました
*2 連続してセットすると上手く行きませんでした

添付ファイル: filepin_layout.png 426件 [詳細] fileLM35DZ_pin.png 202件 [詳細] filefig8_86.png 455件 [詳細] fileL8_13_global_setting.png 181件 [詳細] fileL8_13_ADCINC_1.png 428件 [詳細] fileL8_13_PGA_1.png 400件 [詳細] fileL8_13_ABlock.png 444件 [詳細] fileL8_13_RefMux_1.png 386件 [詳細] fileL8_13_pinout.png 416件 [詳細] fileL8_13_EzI2Cs_1.png 421件 [詳細] fileL8_13_Breadboad.png 439件 [詳細] fileL8_13_I2Cs.png 487件 [詳細] fileL8_13_run.png 413件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-06-23 (木) 10:58:20 (370d)
SmartDoc