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 by 127.0.0.1