ユーザ用ツール

サイト用ツール


サイドバー

Tree

最近の更新

softdev:tempmeter2

温度計を作る2

前回の失敗(でもないが)を勉強し以下仕様で作り直してみた。

  • LM61Bを使う。
  • 増幅度は4倍にして、オフセットは切らない。
  • 時計表示機能を追加する

でで、

LM61B

LM61BはNS(現TI)製の温度センサーである。秋月電子で4個で200円でした。もちろんTO92です。
LM61には、BとCのバージョンがあり、Bの方が精度が高いが、温度範囲が少し狭い。データシートを貼付けておきましょう。
LM61 2.7V, SOT-23 or TO-92 Temperature Sensor

  • 温度勾配が10mV/℃
  • -25℃〜85℃ の測定が可能
  • ±3℃
  • 電源は2.7V〜

内蔵でオフセットが加えられており、温度は下表となる。

Temperature Vout
+50℃ 1100mV
+25℃ 850mV
0℃ 600mV
-25℃ 250mV

よって、4倍の増幅とすればぴったり行く。

増幅率

そのまま、ADCに入れると、5V/1024=4.8mVであり、約0.5℃の精度しかないので扱える最大の整数倍率(あとの計算を楽にする)を設定すると4倍になる。4倍だと、100Kと300KのE24系で実現できる。

時計表示機能

カレンダ時計を付けたいと思う。DR-Z400の時計機能も壊れたまま(これは買ってすぐ壊れた、全く原因不明で10年経ってもなおってない)だし、スクータにも時計は付いてない。

でで、回路図

回路図

Eagleで部品登録がうまく行かなかったので。。。

  • RTC初期化時に設定する必要があるので、SWは二つ。
  • RTCは3Wire
  • CN1はPICkit3接続ポート
  • バイクバッテリ(12V)から5Vをドロッパで作り動作させる。

PICkit3では、PGC,PGD,MCLR端子を使うが、PGC,PGDにはPUを付けられない等の制限がある。

ででで、ソース

ソース

題して、バイクメータ、そのままやんけ。
main初期化部

/*****************************************************
//	for PIC18F1320
//	Bike-Meter
//	開発 キング工房
******************************************************/
#include <htc.h>
#include <delays.h>
#include "delays_usms.h"
#include "lcd_operation.h"
#include "rtc_operation.h"
 
// VCFG1,VCFG0,-,CHS2,CHS1,CHS0,GODONE,ADON
// CHS2,1,0 AN0=000,AN1=001,AN2=010
#define ADON_AN1	0b00000101	
#define ADON_AN2	0b00001001
#define LED_pwr	PORTAbits.RA0
#define LED_paper	PORTAbits.RA4
#define SW_feed	PORTAbits.RA7
#define SW_menu	PORTAbits.RA6
 
void send_dec3(char,int,char,char);
void rtc_init(void);
void rtc_init_mode_in(void);
void get_minmax(int,int);
 
//		配列を引きわたして戻す方法がわからないので、
char	rtc_today[7];	//	グローバルで
int		temp_max,temp_min,volt_max,volt_min;	//最大最小算出為
char	start_time[7];	// 経過時間算出為
//		外部ソースで引用するときは、外部ソース側でextern をつけて再宣言する
 
main()
{
/*
// 書き込み時に使う。最初にないと動作しないみたい。RTCで月を文字で表示する為、EEPROMに書く。
__EEPROM_DATA("J","a","n","F","e","b","M","a");
__EEPROM_DATA("r","A","p","r","M","a","y","J");
__EEPROM_DATA("u","n","J","u","l","A","u","g");
__EEPROM_DATA("S","e","p","O","c","t","N","o");
__EEPROM_DATA("v","D","e","c",0xFF,0xFF,0xFF,0xFF);
*/
	char	a;			// ループ等で使う
	char	led1,keta,rtc_data,cc1u,cc1d;
	int		an1data,tmp10;
//	int		tt;// tt1,tt2は計算用
	unsigned int 	past_time,tt,tt1,tt2,an2data,start_time_int;
	long	tmp10_long;
//	char	tmp10c; //	判定のため仮変数
	char	mm,month[3];
	char	mode;	// 表示モード選択
 
	OSCCON = 0b01111111;	// クロック8MHz
 
	EECON1 = 0b00010001;	// EECON設定ないとEEPROMアクセス不可
 
	ADCON0 = ADON_AN1;		// AN1 on
	ADCON1 = 0xFD;		// AN1 only use
	ADCON2 = 0b10100101;	// Right ,8TAD , Fosc/16
 
	PORTA = 0;// IO 初期化
	PORTB = 0;
	TRISA = 0xEE;				// 0=Out RA0,RA4
	TRISB = 0b10100000;		// RB5 = IN
 
	temp_max = -1000;
	temp_min =  1000;
	volt_max =     0;
	volt_min =   300;
 
	mode=0;
 
	led1 = 1;
	LED_pwr = led1;
	LED_paper = led1;
 
 
	rtc_portinit();
	lcd_init();
 
	if(rtc_get_stat() > 0 ){
		rtc_init_mode_in();
		rtc_init();	// 異常フラグありで初期化
	}	

LCD関係

void shiftreg_lat()
{
	SOLAT = 1; /* latch is rise edge */
	DelayUs(1);
	SOLAT = 0;
}
 
 
void send_data(char data)
{
	signed char c;
	/* send MSB first */
	for(c=7;c>=0;c--){
		SODAT = data>>c;
		DelayUs(1);
		SOCLK = 1;
		DelayUs(1);
		SOCLK = 0;
	}
}
 
void send_to_lcd(char data,char rs)
{
	char ctrl_data;
	/*  data  MSB 7 6 5 4    3    2 1  0  7 6 5 4 3 2 1 0 LSB*/
	/*            0 0 0 BkON BkHi 0 RS E  Data----      -    */
 
	ctrl_data = 0x01 | BKL_AKARUI | rs ; /* E=1,backlight,RS */
	send_data( ctrl_data );
	send_data( data ); 
	shiftreg_lat();
 
	ctrl_data = ctrl_data & 0b11111110 ; /* E=0 */
	send_data( ctrl_data ); 
	send_data( data );
	shiftreg_lat();
}
 
void lcd_locate(char location)
{
	/* location 00h=Row1/Col1 40h=Row2/Col1 */
	location |= 0x80; /* rise bit7=1 */
	send_to_lcd( location , RS0); /*set DDRAM addr to 40h */
}
 
/* write a string of chars to the LCD */
void lcd_puts(const char * s)
{
	while(*s)
		send_to_lcd( *s++ , RS1 );
}

ADCのところ

	while(1){
		ADCON0 = ADON_AN1;
		GO_DONE=1;
		while(GO_DONE);
		an1data = (ADRESH<<8) | ADRESL ;	// Temperatrure
 
		DelayMs(10);
 
		ADCON0 = ADON_AN2;
		GO_DONE=1;
		while(GO_DONE);
		an2data = (ADRESH<<8) | ADRESL ;	// Voltage
		an2data = an2data * 5 * 10 / 256;
 
		tmp10_long = (long)an1data * 500 - 245760;
		tmp10_long =  tmp10_long / 410;
		tmp10 = (int)tmp10_long;

メモリが足りてるので、温度はlongで計算。

softdev/tempmeter2.txt · 最終更新: 2013/07/15 20:25 (外部編集)