文書の表示以前のリビジョンバックリンクPDF の出力全て展開する/折り畳むODT 出力文書の先頭へ この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。 ====== 簡易湿度計(LM74) ====== ===== 概要 ===== 温度センサーには、LM35、LM60、LM61などの、温度に比例した電圧が出力されるタイプの物が、よく使用されています。 そして、このようなセンサーを使用した温度計の仕組み(流れ)は、概ね次のようになります。 【センサー】→【オペアンプ】→【A/D変換+基準電圧】→【マイコン】→【LCD】 また、精度を高めるためには、特にオペアンプ、A/D変換、基準電圧の回路設計に留意する必要があります。 そこで今回は、回路設計の手間を省いて、尚且つ、高い精度の得られる温度計を製作してみます。 センサーには、-55 ℃~+150 ℃の動作温度範囲に対して、12ビット+サインの温度分解能 ( LSB 当たり、0.0625 ℃ ) を備えたナショナル セミコンダクター社の「LM74」を使用します。 <簡易温度計(LM74)の仕様> * 測定範囲:-55℃~150℃ * 温度分解能:0.0625 ℃ * 表示内容:現在温度、最高温度、最低温度、測定経過時間 ===== 動作原理 ===== PICに温度センサーをシリアル接続し、周期的に温度を測定し、結果をLCDに表示します。 ===== 動作原理(ハードウェア) ===== ◎温度センサー * ナショナル セミコンダクター社の「LM74」を使用します。 <LM74の仕様> * 0.0625 ℃の温度分解能 * シャットダウン・モードによる温度読み出し間の節電 * SPI およびMICROWIRE バス・インタフェースを装備 * 電源電圧3.0V あるいは2.65V ~ 5.5V * 電源電流通常動作時265μA ( 代表値)、520μA ( 最大)、シャットダウン時3μA ( 代表値) <LM74の概観と変換基板への実装例> {{:imgpaste:202004:htmikan-20200430-160117.png}}{{:imgpaste:202004:htmikan-20200430-160122.png}} ◎LM74の制御線 * スレーブ出力(SI/O):シリアルバス双方向データライン(PIC←→LM74) * スレーブクロック(SC):シリアルバス用クロック(PIC→LM74) * チップセレクト(CS):チップセレクト用の信号(PIC→LM74) <LM74のブロックダイアグラム> {{:imgpaste:202004:htmikan-20200430-160129.png}} ===== 動作原理(ソフトウェア) ===== ◎温度の測定 * LM74のタイミングチャートに従って、温度レジスタ(16ビット)の内容を取得します。 * 温度レジスタの、D15~D3の13ビットを使用します。 * LM74の温度とデータの関係より、温度値を求めます。 <LM74のタイミングチャート> {{:imgpaste:202004:htmikan-20200430-160159.png?500}} <LM74の温度レジスタ> {{:imgpaste:202004:htmikan-20200430-160203.png?500}} ※D15~D3の13ビットを使用します。 <LM74の温度とデータの関係(1)> {{:imgpaste:202004:htmikan-20200430-160221.png?500}} <LM74の温度とデータの関係(2)> {{:imgpaste:202004:htmikan-20200430-160232.png?500}} ◎最高温度、最低温度の算出 * 現在温度と前回までの最高温度を比較し、最高温度および最低温度を求めます。 * スイッチ(SW)が押下されると、最高温度および最低温度をリセットします。 ◎測定経過時間の算出 * 100msec周期の割り込みを発生させ、それを測定経過時間(時分秒)を計る基準クロックとします。 * スイッチ(SW)が押下されると、測定経過時間をリセットします。 ◎測定結果の表示 * 現在温度、最高温度、最低温度、測定経過時間をLCDに表示します。 ===== 回路図 ===== {{:imgpaste:202004:htmikan-20200430-160256.png}} ===== ソースコード ===== <code c thermo_meter_lm74.c> //********************************************************************** /* <簡易湿度計(LM74)> */ //********************************************************************** //LCD sbit LCD_RS at RA6_bit; sbit LCD_EN at RA7_bit; sbit LCD_D7 at RB7_bit; sbit LCD_D6 at RB6_bit; sbit LCD_D5 at RB5_bit; sbit LCD_D4 at RB4_bit; sbit LCD_RS_Direction at TRISA6_bit; sbit LCD_EN_Direction at TRISA7_bit; sbit LCD_D7_Direction at TRISB7_bit; sbit LCD_D6_Direction at TRISB6_bit; sbit LCD_D5_Direction at TRISB5_bit; sbit LCD_D4_Direction at TRISB4_bit; //LM74 sbit LM74_CS at RA1_bit; sbit LM74_SO at RA2_bit; sbit LM74_SC at RA3_bit; sbit LM74_CS_Direction at TRISA1_bit; sbit LM74_SO_Direction at TRISA2_bit; sbit LM74_SC_Direction at TRISA3_bit; // sbit SW at RA5_bit; // #define BYTE unsigned short #define WORD unsigned int #define DWORD unsigned long //********************************************************************** //■関数宣言 extern void main(); extern int measurement(); extern int convert(int thermo); extern void display(char row, char column, int thermo); extern void init_timer(); extern void interrupt(); extern void trigger(); extern void get_clock(char *msg); extern DWORD clock; extern short start_flg; //********************************************************************** static char buf[16]; //********************************************************************** //■メイン関数 void main() { int thermo, max, min; // OSCCON = 0b01110000; ANSEL = 0b00000000; TRISA = 0b00111111; TRISB = 0b00000110; // Lcd_Init(); Lcd_Cmd(_LCD_CURSOR_OFF); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1, 1, "Thermometer LM74"); Delay_ms(1000); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1, 6, "゚C"); Lcd_Out(2, 6, "゚C"); Lcd_Out(2, 14, "゚C"); // LM74_CS_Direction = 0; LM74_SO_Direction = 1; LM74_SC_Direction = 0; LM74_SC = 0; LM74_CS = 1; // max = 0; min = 1000; clock = 0; start_flg = 1; // init_timer(); // while (1) { //温度の測定と表示(現在値、最高値、最低値) thermo = measurement(); thermo = convert(thermo); max = (thermo < max) ? max : thermo; min = (thermo > min) ? min : thermo; display(1, 1, thermo); display(2, 1, max); display(2, 9, min); //経過時間の取得と表示 get_clock(buf); Lcd_Out(1, 9, buf); // if (SW == 0) { start_flg = 0; clock = 0; max = 0; min = 1000; start_flg = 1; } } } //********************************************************************** //■温度換算関数 void display(char row, char column, int thermo) { if (thermo >= 0) { IntToStr(thermo, buf); buf[1] = ' '; buf[2] = buf[3]; buf[3] = buf[4]; buf[4] = '.'; } else { IntToStr(thermo, buf); buf[1] = '-'; buf[2] = (buf[3] == '-') ? ' ' : buf[3]; buf[3] = (buf[4] == '-') ? ' ' : buf[4]; buf[4] = '.'; } Lcd_Out(row, column, &buf[1]); } //********************************************************************** int convert(int thermo) { double d; int tmp; // if ((thermo & 0b1000000000000000) == 0) { d = thermo >> 3; d = d * 0.0625 * 10; } else { d = (thermo >> 3) & 0x0FFF; d = (d - 4096) * 0.0625 * 10; } tmp = d; return (tmp); } //********************************************************************** //■温度測定関数 int measurement() { DWORD thermo; short cnt; // thermo = 0; LM74_CS = 0; for (cnt = 0; cnt < 16; cnt++) { LM74_SC = 1; if (LM74_SO == 1) { thermo |= 1; thermo <<= 1; } else { thermo |= 0; thermo <<= 1; } LM74_SC = 0; } LM74_CS = 1; thermo >>= 1; return (thermo); } //********************************************************************** //■100msecの周期割り込みを発生させる関数です。 void init_timer() { // CCPの設定 PIE1.CCP1IE = 1; PIR1.CCP1IF = 0; CCP1CON.CCP1M3 = 1; CCP1CON.CCP1M2 = 0; CCP1CON.CCP1M1 = 1; CCP1CON.CCP1M0 = 1; CCPR1L = 0xA8; // 100msec...クロックが8Mhzの時 CCPR1H = 0x61; // 100msec...(1÷16000000)*4*8*25000(0x61A8) // TIMER1の設定 PIE1.TMR1IE = 0; PIR1.TMR1IF = 0; TMR1L = 0; TMR1H = 0; T1CON.TMR1CS = 0; T1CON.T1CKPS0 = 1; T1CON.T1CKPS1 = 1; T1CON.TMR1ON = 1; // INTCON.PEIE = 1; INTCON.GIE = 1; } //********************************************************************** //■割り込み関数です。 DWORD clock = 0; short start_flg = 0; // void interrupt() { if (PIR1.CCP1IF == 1) { PIR1.CCP1IF = 0; // if (start_flg == 1) { clock++; } } } //********************************************************************** //■測定タイミングをチェックする関数です。 void trigger() { DWORD tmp; // tmp = clock; while ((tmp % 10) != 0) { Delay_ms(1); } } //********************************************************************** void ByteToStr2(unsigned short number, char *output) { ByteToStr(number, output); output[0] = (output[1] == ' ') ? '0' : output[1]; output[1] = output[2]; output[2] = 0x00; } //********************************************************************** //経過時間取得関数 void get_clock(char *msg) { DWORD tmp; BYTE hh, mm, ss; // tmp = clock; tmp /= 10; hh = tmp / 3600; mm = (tmp % 3600) / 60; ss = (tmp % 3600) % 60; ByteToStr2(hh, buf); buf[2] = ':'; ByteToStr2(mm, &buf[3]); buf[5] = ':'; ByteToStr2(ss, &buf[6]); buf[8] = ' '; } //********************************************************************** </code> ===== 動作確認 ===== {{:imgpaste:202004:htmikan-20200430-160425.png?500}} 左上:現在温度、右上:測定経過時間 左下:最高温度、右下:最低温度 {{:imgpaste:202004:htmikan-20200430-160441.png?500}} <callout type="warning" title="著作権表示 copyright notice"> このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。[[elechobby:picdic:picdic|詳細]] This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.[[elechobby:picdic:picdic|Details]] </callout> elechobby/picdic/pic16f88/153.txt 最終更新: 2025/10/17 14:29by 127.0.0.1