Arduinoとフリスクで赤外線温度計を自作してみた
あむちょです。
今回は電子工作
たまに無性にやりたくなるフリスク工作。
以前バイクのタイヤ温度計測にかった非接触温度センサーが余ってたので3Dプリンター用にフリスクに入れてみました。
完成品はこんな感じ。片手撮影なのでブレブレ。
目次
まず用意するのがフリスクケースですが、実はフリスクじゃありません。

ガンタブです。
普通のフリスクと比べて厚みが2mmほど多く、2mmのおかげで詰め込めるモジュールが変わってくるのでコンビニ売ってた時に買い込んでおきました。

フリスクっぽいケースコレクション。
MLX90614の使い方
今回使った温度センサーはこれ。

-70℃から380℃の範囲でスポット温度をはかれます。周辺温度もはかれるので気温計みたいにも使えます。

I2C接続で電源の他に2本繋ぐだけで簡単。
[amazonjs asin=”B06XHJZ24W” locale=”JP” title=”WINGONEER GY-906 MLX90614 ESF-BAA-000-TU-ND Arduino用赤外線温度計IRセンサー”]
0.96インチOLEDディスプレイの使い方
温度表示は液晶を使います。

これもI2C接続です。128×64ピクセルで上1/3が黄色表示の物です。
ライブラリーはAdafruit SSD1306とAdafruit GFX Libraryが必要です。
そのままだとエラーがでるのでAdafruit_SSD1306.hの73行目あたり
// #define SSD1306_128_64 #define SSD1306_128_32 // #define SSD1306_96_16
ここを解像度にあったものをコメントアウトさせておきます。
ライブラリーの描画の仕方はここが参考になります。ArduinoでOLEDディスプレイに色々表示する
[amazonjs asin=”B011KITMUY” locale=”JP” title=”DIYMALL iic i2c OLEDモジュール ディスプレイ 0.96インチ ブルー&イエロー51マイクロコントローラ12864 for Arduino”]
ハードウェア
使ったArduinoはArduino pro micro。
[amazonjs asin=”B01B26MAR6″ locale=”JP” title=”Pro Micro 5V/16MHz”]
フリスクに入れるとなるとこの大きさじゃないと厳しい。
スイッチにより、スポット温度と周辺温度を切り替えてます。

スイッチを入れるスペースがないので鉄板でスイッチを作成。
電池はcr2025を二枚重ね6v、Vinピンがないのでダイオードで電圧効果させて使ってますが。後から知ったがRAWピンに接続すればVccから5vにレギュレートされるらしいです。
電池ケースは極限まで薄くしてクリアランスを確保。

フリスクを開くとスイッチオンになるように、ケースの裏につけた突起におされてオンになるよう金属版を向かい合わせてとりつけ。

ソフトウェア
やってることはセンサーからデータをもらって液晶に表示しているだけです。
スイッチによる割り込みがあったら温度センサーのモードを切り替えてます。
#include <Adafruit_SSD1306.h>
#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <i2cmaster.h>
#include <Wire.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
volatile int mode = 0;
volatile unsigned long time;
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11111111, B11100000,
B11111111, B11111000,
B01111111, B11111111,
B00111111, B11111111,
B00011111, B11111100,
B00001111, B11110000,
B00011111, B11100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
void setup() {
i2c_init(); //Initialise the i2c bus
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
//PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups
pinMode(0,INPUT_PULLUP);
attachInterrupt(2, fall, FALLING);
time = millis();
display.begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS);
display.display();
delay(100);
//logoマーク表示
display.clearDisplay();
display.drawRoundRect(2,16,128-4,64-16,display.height()/4, WHITE);
//thermometer
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Thermometer");
//fieldWalking
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(10,24);
display.print("field\n Walking");
display.drawBitmap(90,22,logo16_glcd_bmp,16,16, 1);
display.display();
//反転演出
for (int i=0;i<6;i++) {
if (i%2 == 0) {
display.invertDisplay(true);
} else {
display.invertDisplay(false);
}
display.display();
delay(50);
}
delay(1000);
display.clearDisplay();
}
void loop() {
char buf[10];
float t = temp();
dtostrf(t,7,1,buf);
//sprintf(buf," %f",t);
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
if(mode == 0)display.println("Mode\n Spot");
else{
display.println("Mode\n Around");
}
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("Temp");
display.setTextSize(1);
display.println("");
display.setTextSize(3);
display.print(buf);
display.display();
delay(200);
display.clearDisplay();
}
float temp(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
if(mode == 0)i2c_write(0x07); //スポット計測
else{
i2c_write(0x06); //周辺温度
}
// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();
//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
double tempData = 0x0000; // zero out the data
//int frac; // data past the decimal point
// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor) - 0.01;
return tempData-273.15;
}
void fall(){
//チャタリング対策
if(millis()-time < 200)return;
time = millis();
if(mode == 0)mode = 1;
else{
mode = 0;
}
}
Arduinoでは、floatのsprintfが使えないにでかわりにdtostrfを使います。
自作の金属板スイッチではスイッチが触れる瞬間にオンオフが高速で繰り替えされる(チャタリング)ので、割り込みが発生した後200m秒間は割り込みを無視しています。
便利かどうかといわれると
あんま使ってない
[ad][ad]