Arduinoとフリスクで赤外線温度計を自作してみた

あむちょです。

今回は電子工作

PR アプリ作ってます

たまに無性にやりたくなるフリスク工作。

以前バイクのタイヤ温度計測にかった非接触温度センサーが余ってたので3Dプリンター用にフリスクに入れてみました。

完成品はこんな感じ。片手撮影なのでブレブレ。

目次

まず用意するのがフリスクケースですが、実はフリスクじゃありません。

ガンタブ

ガンタブです。

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

フリスクっぽいケース

フリスクっぽいケースコレクション。

MLX90614の使い方

今回使った温度センサーはこれ。

MLX90615

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

ピン配列

I2C接続で電源の他に2本繋ぐだけで簡単。

0.96インチOLEDディスプレイの使い方

温度表示は液晶を使います。

IMG_8213

これも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ディスプレイに色々表示する

ハードウェア

使ったArduinoはArduino pro micro。

フリスクに入れるとなるとこの大きさじゃないと厳しい。

スイッチにより、スポット温度と周辺温度を切り替えてます。

スイッチ

スイッチを入れるスペースがないので鉄板でスイッチを作成。

電池は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]

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です