NullなNuma

自由気ままに何か書く

リフロー炉製作(2)

前回はオーブントースターを改造したので
制御の部分を作ります

製作

簡単に扱えるArduinoを使います

使用した部品

  • MAX31855(温度計)
  • タクトスイッチ(スタート用)
  • 圧電スピーカー
  • OLEDディスプレイ
  • SSRキット

回路を組むとこんな感じ
SSRキット
f:id:nullnuma:20170727225813j:plain
Arduinoとその仲間たち
f:id:nullnuma:20170727225848j:plain

はんだペースト
Aliで輸入したけどちゃんとつかえたので当たりをひいた
f:id:nullnuma:20170727225937j:plain

プログラム

当初はPID制御で温度調節をしようと考えていたのですが
うまく動作しているのか怪しかったので
単純に設定温度を超えたかどうかでON/OFFを切り替えることにしました

プログラムはこんな感じですが(長ったらしいし載せなくてもいいんじゃないか)

#include <SPI.h>
#include "Adafruit_MAX31855.h"
#include <U8glib.h>
/*
   リフロー手順
   1.加熱ステージ1
   2.予熱ステージ
   3.加熱ステージ2
   4.リフローステージ
   5.冷却ステージ
*/

#define Wait    0
#define Heat1   1
#define Preheat 2
#define Heat2   3
#define Reflow  4
#define Cool    5

int Profile[6][2] = {
  {  0,  0},
  {140,  0},  //Heat1
  {160, 60},  //Preheat
  {225,  0},  //Heat2
  {230, 20},  //Reflow
  {   0, 0}   //Cool
};

//ピンアサイン
#define Pin_SSR     8
#define Pin_Buzzer  9

#define Pin_BTN_Start 6

#define Pin_MAXDO   3
#define Pin_MAXCS   4
#define Pin_MAXCLK  5

//LCD
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST);
//Temp
double TargetTemp, Temp;
int WindowSize = 5000;
unsigned long windowStartTime;
//K type thermocouple
Adafruit_MAX31855 thermocouple(Pin_MAXCLK, Pin_MAXCS, Pin_MAXDO);

byte state;
byte beforestate = 0;

byte temp[256];
byte temp_cnt;

byte TargetFlag = 0;
unsigned long HeatingTime;


void GetTemp() {
  double c = thermocouple.readCelsius();
  double inter = thermocouple.readInternal();
  if (!isnan(c)) {
    Temp = c;
    temp_cnt++;
    temp[temp_cnt] = (byte)(c/2);
  }else{
    Serial.println("error get temp");
  }
  return 0;
}

void SetTemp() {
  TargetTemp = Profile[state][0];
  windowStartTime = millis();
}
void ControlSSR() {
  if (0 < state && state < 5) {
    if(TargetTemp > Temp){
      digitalWrite(Pin_SSR, HIGH);
    } else {
      digitalWrite(Pin_SSR, LOW);
    }
  }
}

void DrawState() {
  String str_num = String(state,DEC);
  String str = String("State:" + str_num);
  u8g.drawStr( 0, 20, str.c_str());

  if(TargetFlag > 0){
    str_num = String(Profile[state][1]-(millis()/1000 - HeatingTime),DEC);
    str = String(str_num + "s");
    u8g.drawStr( 64, 20, str.c_str());
  }
  
  str_num = String(temp[temp_cnt] * 2,DEC);
  str = String("Temp :" + str_num);
  u8g.drawStr( 0, 40, str.c_str());
  
  str_num = String((Profile[state][0]));
  str = String("SetTemp :" + str_num);
  u8g.drawStr( 0, 60, str.c_str());

}
void DrawGraph() {
  //Required firstPage
  int i;
  for (i = 0; i < 256; i++) {
    u8g.drawPixel(255-i, 64-temp[(temp_cnt + i) % 256]/2);
  }
}
void RefreshLCD() {
  u8g.firstPage();
  do {
    switch (state) {
      case Wait:
        DrawState();
        break;
      case Heat1:
      case Preheat:
      case Heat2:
      case Reflow:
      case Cool:
        if (millis() / 2000 % 2) {
          DrawGraph();
        } else {
          DrawState();
        }
        break;
    }

  } while ( u8g.nextPage() );
}

void CalcHeat(){
  if(TargetFlag){
    //一定加熱
    if((millis()/1000 - HeatingTime) > Profile[state][1]){
      TargetFlag = 0;
      state++;
      SetTemp();
    }
  }else{
    if(Profile[state][0] < temp[temp_cnt]*2){
      TargetFlag = 1;
      HeatingTime = millis()/1000;
    }
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  //ピンモード
  pinMode(Pin_SSR, OUTPUT);
  pinMode(Pin_BTN_Start, INPUT_PULLUP);
  //LCD
  u8g.setColorIndex(1);
  u8g.setFont(u8g_font_8x13r);
  state = 0;
}

void loop() {
  beforestate = state;
  GetTemp();
  switch (state) {
    case Wait:
      if (digitalRead(Pin_BTN_Start) == LOW) {
        //Start!
        state++;
        SetTemp();
        TargetFlag = 0;
        Serial.print("  Next Heat1 Stage");
        tone(Pin_Buzzer,1500,100);
      }
      break;
    case Heat1:
      CalcHeat();
      break;
    case Preheat:
      CalcHeat();
      break;
    case Heat2:
      CalcHeat();
      if(beforestate != state){
        tone(Pin_Buzzer,1000,200);
      }
      break;
    case Reflow:
      CalcHeat();
      if(beforestate != state){
        tone(Pin_Buzzer,1500,1000);
      }
      break;
    case Cool:
      if(beforestate != state){
        tone(Pin_Buzzer,1000,1000);
      }
      break;
  }
  ControlSSR();
  RefreshLCD();
  delay(100 - millis() % 100);
}

Let's リフロー!

はんだペーストを基板に載せてその上に部品を載せる
小さいパッドにはんだペーストを載せるのはなかなかきつい
f:id:nullnuma:20170727230051j:plain
そして作ったリフロー炉に入れれば
f:id:nullnuma:20170727230019j:plain
はいできあがり、光らない…。1個だけ光らない…。
f:id:nullnuma:20170727230157j:plain
LEDチップの端子と基板は導通が全てあるけど光らなかったので
もともとLEDチップが死んでいたのかなとか考えた

実装する前にちゃんと動作するか確かめるためのものが
必要だということがわかりました

次回はユニバーサル基板で実装しようと思います

ハイローズ(Hi-rose) オーブントースター HR-T121

ハイローズ(Hi-rose) オーブントースター HR-T121

K型熱電対温度センサモジュールキット(SPI接続)MAX31855使用 5V版

K型熱電対温度センサモジュールキット(SPI接続)MAX31855使用 5V版