Asi_aのアイコン画像
Asi_a 2021年05月20日作成 (2021年12月25日更新) © MIT
製作品 製作品 閲覧数 10451
Asi_a 2021年05月20日作成 (2021年12月25日更新) © MIT 製作品 製作品 閲覧数 10451

秋月サーモパイルで非接触温度計を作った

秋月サーモパイルで非接触温度計を作った

はじめに

elchika世間がObniz一色な中何も関係ない記事を投稿していくスタイル。
2月に秋月が売り出したやっすいサーモパイルを使ってナウい感じな非接触温度計を作りたかった。

サーモパイルとは

サーモパイルは変な使い方をしている熱電対という理解をしてもらえればいいと思う。

まず、熱電対の片方の金属片に光を当てると温まってそれで電位差が生じる。光が強ければより温まってより大きな電位差が生じる。サーモパイルでは、入力光をフィルターで、室温付近での熱放射の主成分である赤外線付近に限定してしまうことで、熱放射のエネルギーがだいたい分かるというもの、らしい。

これによって彼我の温度を得られるが、実温度は得られないので、サーミスタを同梱してサーモパイル自体の温度も得るタイプが一般ぽい。

全体的な方針

  • 電源にはNi-MHx2を使用し、HT7733Aで3.3Vに昇圧し、アナログ系統にはシャントレギュレーターで3.3Vを2.495Vに降圧したものを用いる。
  • サーモパイルとサーミスタの出力はオペアンプを通してPICに送る。
  • 温度表示は定番の8x2のI2CのLCD。
  • 細かい調整などは回路側ではなく、マイコン側で頑張る。

使用した主要な部品リスト

部品 点数 備考
サーモパイル ISB-TS45D 1 I-15815、本作の目玉、実際安い
PIC32MX120F032B-I/SP 1 I-05850、何故か大量に持ってた
AD8506 1 I-04568、面実装オペアンプ、変換基板に載ってるやつもある
HT7733A 1 I-02799、昇圧DCDC制御IC
TL431 1 I-12018、シャントレギュレータ
I2C接続小型LCDモジュール変換キット 1 K-06795、8x2のやつ
プラケース SK-5 1 P-00076、単3が横に入るもののうち最小(多分)

その他に基板、電池ボックス、コネクタ類、抵抗、コンデンサ、マイクロインダクタ、ショットキーバリアダイオードなどを使用。

回路図

回路図、水魚堂で作成

典型的な非反転とボルテージフォロアなので特に難しくはない。C3の10uはどうしても50Hzのノイズが乗るのでつけた。バッテリー駆動なので出所がわからない。

PICと液晶周りの回路は割愛させて頂いた。あとに載せるピンアサイン画像を見てもらえればだいたい分かると思う。それにどうせみんなArduinoにつなげちゃうんでしょ。AD変換の正の基準電圧(Vref+)には2.495Vがつながっていることに注意。

プログラム

MPLAB X + XC32 + Microchip Harmony3で開発した。Microchip Harmony3は起動するのに何故かクッッッッッソ時間がかかるので困る(誰か解決策教えて下さい)。Microchip Harmonyでは以下のように設定した。

使用モジュール

クロック設定、見切れている部分もあるが必要なところは全部載せれてるはず

ピンアサイン

AD変換

UART
UART2を使うと、書き込み用に出した端子をそのままシリアル通信に使える(小技)。

Timer1

I2C

プログラムは基本的にMicrochip Harmony3の自動生成コードから書き起こしている。
変更部分のみ掲載。

main.c

#include <stddef.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> #include "definitions.h" volatile bool t1_int = false; double ADC2ThermistorTemp(int value) { const double a = -0.08758141505; const double b = 69.96186904; return a * (double) value + b; } double ADC2ThermopileTemp(int value) { const double a = 0.4987508246; const double b = -98.0; return a * (double) value + b; } void delay(int delay_time) { for (int i = 0; i < delay_time; i++) { while (!t1_int); t1_int = false; } } const uint16_t LCDaddr = 0x3e; //0x7c const uint8_t initCommands[] = {0x38, 0x39, 0x14, 0x70, 0x56, 0x6C, 0x38, 0x0C, 0x01}; void LCDSendData(bool isInst, uint8_t data) { uint8_t d[2] = {isInst ? 0x00 : 0x40, data}; I2C1_Write(LCDaddr, d, 2); while (I2C1_IsBusy()); delay(2); } void LCDSendData2(bool isInst, const uint8_t *data, int size) { for (int i = 0; i < size; i++)LCDSendData(isInst, data[i]); } void LCDSendMsg(const char *data, int size) { uint8_t msg[40] = {0x80, 0x80}; int msg_size = 2; for (int i = 0; (i < size) && (i < 16); i++) { if (i == 8) { msg[msg_size] = 0x80; msg[msg_size + 1] = 0xC0; msg_size += 2; } msg[msg_size] = 0xC0; msg[msg_size + 1] = data[i]; msg_size += 2; } I2C1_Write(LCDaddr, msg, msg_size); while (I2C1_IsBusy()); delay(2); } void LCDInit(void) { delay(40); LCDSendData2(true, initCommands, sizeof (initCommands)); } int main(void) { /* Initialize all modules */ SYS_Initialize(NULL); puts("start\n"); TMR1_Start(); TMR3_Start(); LCDInit(); while (true) { delay(100); char m[17]; double A1 = ADC2ThermopileTemp(ADC1BUF0); double A2 = ADC2ThermistorTemp(ADC1BUF1); snprintf(m, sizeof (m), "P:%4.1f%cCT:%4.1f%cC", A1 + A2, 0xdf, A2, 0xdf); LCDSendMsg(m, strlen(m)); //printf("%d,%d\n", ADC1BUF0, ADC1BUF1); } /* Execution should not come here during normal operation */ return (EXIT_FAILURE); }

interrupt.c

#include "definitions.h" #include "test.h" //<-追加 void TIMER_1_InterruptHandler( void ); void I2C_1_InterruptHandler( void ); void __ISR(_TIMER_1_VECTOR, ipl1AUTO) TIMER_1_Handler (void) { TIMER_1_InterruptHandler(); t1_int = true; //<-追加 } void __ISR(_I2C_1_VECTOR, ipl1AUTO) I2C_1_Handler (void) { I2C_1_InterruptHandler(); }

test.h

#pragma once extern volatile bool t1_int;

ビルドするときは-std=c99オプションをお忘れなく。

温度算出はADC2ThermistorTemp()及びADC2ThermopileTemp()の実装を見てもらえればわかるが、1次近似である。
データシートから計算した値をもとに、サーミスターは0℃から40℃、サーモパイルは温度0℃から+20℃まででそれぞれ1次近似して、それから実機で校正した。

XC32はC++も使えるが、リンクされるライブラリの最適化に問題があるらしく基本使えないと思っていい。
これは全く余談だがC++とか最早いいからRustとか使わせてほしい、Microchipさんどうでしょう。明らかに組み込み系に必要なんですが。

完成品

トップビュー

内部、液晶の固定はビニテw

上部にサーモパイル、一応穴を開けている

裏、無計画な配線が見えてしまう

デモ

左がお湯入り、右が氷水入りの紙コップです。

ここに動画が表示されます

市販のサーモパイル式非接触体温計は?

最近額に向けてピピッとやるタイプの非接触温度計が流行っているが、今回のように素直な実装では明らかに体温は測れないのでどうしているのか気になって調べてみたところ、タニタのページでは

本器は、人の額の表面から放射される赤外線量を測定し、舌下温度に換算してデジタル表示します(体温測定モード)。
また、物体の表面から放射される赤外線量を測定し、温度に換算してデジタル表示します(温度測定モード)。

とあった。ナルホドナー。換算がうまく機能するために「使用上の注意」にあるように制約が多くなってしまうのは頷ける。でも消費者がこれすべて守れるのかどうか……?

言い訳など

  • オペアンプ内蔵のPICでやればスマートにできたかもしれないけどPIC32とオペアンプの在庫があったから仕方がない
  • 今回使ったサーモパイルのメーカーのページには後継品?のISB-TS45Hしか掲載されていない。こちらの方が起電力も大きいしデータシートも見やすいのだが・・・。
  • フルネルレンズなどは試していない。やったらどうなるかは気になるが、検知角度が狭くなるならともかく広くなっても仕方がない気もする。
  • 校正、実はうまくやれてない。1度単位で変えれる熱源ください。恒温槽も。
  • 逆に、同じ温度のものを図ったときの再現性はとても良いので、校正がうまくやれればだいぶ精度良く計れそうである。

おわりに

アナログ回路は難しいすね。

参考

付録

https://gist.github.com/asi-msk/9b022297248a49684a1c8892089d7bad
データシートから起電力引っ張ってくるのはめんどくさかろう?

1
Asi_aのアイコン画像
PICとかすきです
  • Asi_a さんが 2021/05/20 に 編集 をしました。 (メッセージ: 初版)
  • Asi_a さんが 2021/12/25 に 編集 をしました。
  • Opening
    andyのアイコン画像 andy 2022/02/15

    こんにちはAsi_a、私は最近ISB-TS45Dを購入しました。 「PICマイクロコントローラー」を持っていないので、arduinoに接続したかったので、抵抗器など使用している部品のわかりやすい図や写真をアップロードしてください。
    ISB-TS45Dとarduinoを使って非接触温度計を作りたいです。
    できれば助けてください。
    ありがとうございます。

    0 件の返信が折りたたまれています
ログインしてコメントを投稿する