オーブントースターでリフロー

あくまでもメモです。自己責任実施してください。
半田の融解温度や作る基板で色々変わると思います。

#はじめに
necobitさんの動画を見ていて、これならトースター無改造で行けそうみたいなノリで
https://www.youtube.com/watch?v=M0lduil1xF0

#使用したもの
オーブントースター　象印　EQ-AG22-BA-JK　https://online.nojima.co.jp/commodity/1/2810000079429/
M5Stack Basic＋Bus Module
https://wiki.seeedstudio.com/Grove-I2C_Thermocouple_Amplifier-MCP9600/
熱電対　https://www.amazon.co.jp/dp/B015E4EBL0 先っぽの樹脂はとっています。　熱電対の先に少し銅テープがあると良い。面積を稼ぐため。熱電対の銅線から逃げていく熱量と入ってくる熱量のバランスが悪いと低く表示

SSR　https://akizukidenshi.com/catalog/g/gI-08620/
電子部品少々

冷蔵庫（クリームはんだ保存用：8℃に設定）　https://www.amazon.co.jp/dp/B08QM9PQCS

#回路図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/cdb930ad-b020-22c3-11be-5ac5507ab696.png)

#スケッチ
１８３℃のクリームはんだで試行錯誤してみて、
熱電対の温度表示が少し低め？(160℃くらいではんだが溶ける）
SSRが切れて10℃くらい上がる
プロファイルを色々見て、結局
　はんだが溶ける前の温度でフラックスを活性化90秒
　半田のとける183から30秒くらいでOFF最大温度は205(200±10)℃(210℃少し上まで上がる）白い基板が少し黄色になるが許容範囲。パッケージ温度にはいかないように、設定
　冷却時間も含め183℃以上を60秒程度維持できるように
みたいな感じで以下の様になりました。
https://nwws.jpn.org/Toster/Control.zip 

スケッチ部分

```
#include <M5Stack.h>
#include <Wire.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_I2CRegister.h>
#include "Adafruit_MCP9600.h"
#include "START_XBM.h"
#include "STOP_XBM.h"
#include "now_XBM.h"
#include "mode0_XBM.h"
#include "mode1_XBM.h"
#include "mode2_XBM.h"
#include "mode3_XBM.h"
#include "mode4_XBM.h"
#include "mode5_XBM.h"
#define SsrPin G26

#define mode1_Temp 140.0f
#define mode2_Temp 140.0f
#define mode2_TempWidth 5.0f
#define mode2_Time 90000 //90s
#define mode3_Temp 183.0f
#define mode4_Temp 200.0f
#define mode4_TempWidth 10.0f
#define mode4_Time 30000 //30s
#define mode5_Temp 183.0f
#define mode6_Temp 150.0f

TFT_eSprite spr_main0 = TFT_eSprite(&M5.Lcd);
TFT_eSprite spr_main1 = TFT_eSprite(&M5.Lcd);
TFT_eSprite spr_btnA = TFT_eSprite(&M5.Lcd);
TFT_eSprite spr_btnB = TFT_eSprite(&M5.Lcd);
TFT_eSprite spr_btnC = TFT_eSprite(&M5.Lcd);
TFT_eSprite spr_Graph = TFT_eSprite(&M5.Lcd);

unsigned long totalMillis = 0, mode2Millis = 0, mode4Millis = 0, mode5Millis = 0;
byte mode = 0;
Adafruit_MCP9600 mcp;

void btnAEnable() {
  spr_btnA.fillScreen(TFT_BLACK);
  spr_btnB.fillScreen(TFT_BLACK);
  spr_btnC.fillScreen(TFT_BLACK);
  spr_btnA.drawXBitmap(0, 0, START, START_width, START_height, TFT_WHITE);
  spr_btnB.drawXBitmap(0, 0, STOP, STOP_width, STOP_height, TFT_DARKGREY);
  spr_btnC.drawXBitmap(0, 0, STOP, STOP_width, STOP_height, TFT_DARKGREY);
  spr_btnA.pushSprite(40, 220);
  spr_btnB.pushSprite(130, 220);
  spr_btnC.pushSprite(220, 220);
}
void btnADisenable() {
  spr_btnA.fillScreen(TFT_BLACK);
  spr_btnB.fillScreen(TFT_BLACK);
  spr_btnC.fillScreen(TFT_BLACK);
  spr_btnA.drawXBitmap(0, 0, START, START_width, START_height, TFT_DARKGREY);
  spr_btnB.drawXBitmap(0, 0, STOP, STOP_width, STOP_height, TFT_WHITE);
  spr_btnC.drawXBitmap(0, 0, STOP, STOP_width, STOP_height, TFT_WHITE);
  spr_btnA.pushSprite(40, 220);
  spr_btnB.pushSprite(130, 220);
  spr_btnC.pushSprite(220, 220);
}

void setup() {
  M5.begin(true, false, true, true);
  M5.Speaker.setBeep(1000, 100);
  pinMode(SsrPin, OUTPUT);
  digitalWrite(SsrPin, HIGH);
  spr_main0.setColorDepth(8);
  spr_main1.setColorDepth(8);
  spr_btnA.setColorDepth(8);
  spr_btnB.setColorDepth(8);
  spr_btnC.setColorDepth(8);
  spr_Graph.setColorDepth(8);

  spr_main0.createSprite(160, 110);
  spr_main1.createSprite(160, 110);
  spr_btnA.createSprite(60, 20);
  spr_btnB.createSprite(60, 20);
  spr_btnC.createSprite(60, 20);
  spr_Graph.createSprite(320, 110);
  Serial.begin(115200);
  if (! mcp.begin(I2C_ADDRESS)) {
    Serial.println("Sensor not found. Check wiring!");
    while (1);
  }

  Serial.println("Found MCP9600!");

  mcp.setADCresolution(MCP9600_ADCRESOLUTION_16);  
  Serial.print("ADC resolution set to ");
  switch (mcp.getADCresolution()) {
    case MCP9600_ADCRESOLUTION_18:   Serial.print("18"); break;
    case MCP9600_ADCRESOLUTION_16:   Serial.print("16"); break;
    case MCP9600_ADCRESOLUTION_14:   Serial.print("14"); break;
    case MCP9600_ADCRESOLUTION_12:   Serial.print("12"); break;
  }
  Serial.println(" bits");

  mcp.setThermocoupleType(MCP9600_TYPE_K);
  Serial.print("Thermocouple type set to ");
  switch (mcp.getThermocoupleType()) {
    case MCP9600_TYPE_K:  Serial.print("K"); break;
    case MCP9600_TYPE_J:  Serial.print("J"); break;
    case MCP9600_TYPE_T:  Serial.print("T"); break;
    case MCP9600_TYPE_N:  Serial.print("N"); break;
    case MCP9600_TYPE_S:  Serial.print("S"); break;
    case MCP9600_TYPE_E:  Serial.print("E"); break;
    case MCP9600_TYPE_B:  Serial.print("B"); break;
    case MCP9600_TYPE_R:  Serial.print("R"); break;
  }
  Serial.println(" type");

  mcp.setFilterCoefficient(2); 
  Serial.print("Filter coefficient value set to: ");
  Serial.println(mcp.getFilterCoefficient());

  mcp.setAlertTemperature(1, 30);
  Serial.print("Alert #1 temperature set to ");
  Serial.println(mcp.getAlertTemperature(1));
  mcp.configureAlert(1, true, true);  // alert 1 enabled, rising temp

  mcp.enable(true);

  Serial.println(F("------------------------------"));
  btnAEnable();
}

void loop() {
  M5.update();
  // float temp = 0;
  // get_temperature(&temp);
  float temp = mcp.readThermocouple();
  if (M5.BtnB.wasPressed())
  { mode = 0;
    digitalWrite(SsrPin, LOW);
    M5.Speaker.beep();
    btnAEnable();
  }
  if (M5.BtnC.wasPressed())
  { mode = 0;
    digitalWrite(SsrPin, LOW);
    M5.Speaker.beep();
    btnAEnable();
  }
  if (digitalRead(SsrPin) == LOW)
    spr_main0.fillScreen(TFT_WHITE);
  else spr_main0.fillScreen(TFT_PINK);
  spr_main0.drawXBitmap(0, 0, now, now_width, now_height, TFT_BLACK);
  spr_main0.setTextColor(TFT_BLACK);
  spr_main0.setTextDatum(TR_DATUM);
  spr_main0.drawNumber(temp, 159, 27, 4);
  if (mode != 0) {
    spr_main0.drawNumber((millis() - totalMillis) / 1000, 159, 109, 4);
  }
  spr_main0.pushSprite(0, 0);

  spr_main1.fillScreen(TFT_WHITE);

  switch (mode) {
    case 0: //待機状態
      digitalWrite(SsrPin, LOW);
      spr_main1.drawXBitmap(0, 0, mode0, mode0_width, mode0_height, TFT_BLUE);

      if (M5.BtnA.wasPressed())
      { mode = 1;
        btnADisenable();
        M5.Speaker.beep();
        totalMillis = millis();
        digitalWrite(SsrPin, HIGH);
        spr_Graph.fillScreen(TFT_BLACK);
        spr_Graph.drawLine(20, 0, 20, 100, TFT_WHITE);
        spr_Graph.drawLine(20, 100, 320, 100, TFT_WHITE);
        spr_Graph.setTextDatum(CR_DATUM);
        spr_Graph.setTextColor(TFT_WHITE);
        spr_Graph.drawString("100", 20, 100 - 100 / 2.5, 2);
        spr_Graph.drawString("200", 20, 100 - 200 / 2.5, 2);
        spr_Graph.drawLine(20, 100 - 183 / 2.5, 320, 100 - 183 / 2.5, TFT_RED);
      }
      break;
    case 1:  //昇温
      if (temp >= mode1_Temp) {
        mode = 2;
        mode2Millis = millis();
        M5.Speaker.beep();
      } else {
        spr_main1.drawXBitmap(0, 0, mode1, mode1_width, mode1_height, TFT_ORANGE);
        spr_main1.setTextDatum(TR_DATUM);
        spr_main1.setTextColor(TFT_ORANGE);
        spr_main1.drawNumber(mode1_Temp, 159, 27, 4);
      }
      break;
    case 2://予熱ステージ
      if (millis() > (mode2Millis + mode2_Time)) {
        mode = 3;
        M5.Speaker.beep();
        digitalWrite(SsrPin, HIGH);
      } else {
        if (temp > (mode2_Temp + mode2_TempWidth / 2.0f))  digitalWrite(SsrPin, LOW);
        if (temp < (mode2_Temp + mode2_TempWidth / 2.0f))  digitalWrite(SsrPin, HIGH);
        spr_main1.drawXBitmap(0, 0, mode2, mode2_width, mode2_height, TFT_ORANGE);
        spr_main1.setTextColor(TFT_ORANGE);
        spr_main1.setTextDatum(TR_DATUM);
        spr_main1.drawNumber(mode2_Temp, 159, 27, 4);
        spr_main1.drawNumber(mode2_Time / 1000, 159, 54, 4);
        spr_main1.drawNumber((millis() - mode2Millis) / 1000, 159, 82, 4)  ;
      }
      break;
    case 3:
      if (temp >= mode3_Temp) {
        mode = 4;
        mode4Millis = millis();
        M5.Speaker.beep();
      } else {
        spr_main1.drawXBitmap(0, 0, mode3, mode3_width, mode3_height, TFT_RED);
        spr_main1.setTextDatum(TR_DATUM);
        spr_main1.setTextColor(TFT_RED);

        spr_main1.drawNumber(mode3_Temp, 159, 27, 4);

      }
      break;
    case 4://半田フローステージ
      if (millis() > (mode4Millis + mode4_Time)) {
        mode = 5;
        digitalWrite(SsrPin, LOW);
        M5.Speaker.beep();
      } else {
        if (temp > (mode4_Temp + mode4_TempWidth / 2.0f))  digitalWrite(SsrPin, LOW);
        if (temp < (mode4_Temp + mode4_TempWidth / 2.0f))  digitalWrite(SsrPin, HIGH);
        spr_main1.drawXBitmap(0, 0, mode4, mode4_width, mode4_height, TFT_RED);
        spr_main1.setTextColor(TFT_RED);
        spr_main1.setTextDatum(TR_DATUM);
        spr_main1.drawNumber(mode4_Temp, 159, 27, 4);
        spr_main1.drawNumber(mode4_Time / 1000, 159, 54, 4);
        spr_main1.drawNumber((millis() - mode4Millis) / 1000, 159, 82, 4)    ;
      }
      break;
    case 5:
      if (temp < mode5_Temp) {
        mode = 6;
        mode5Millis = (millis() - mode4Millis) ;
        M5.Speaker.beep();
      } else {
        spr_main1.drawXBitmap(0, 0, mode5, mode5_width, mode5_height, TFT_RED);
        spr_main1.setTextColor(TFT_RED);
        spr_main1.setTextDatum(TR_DATUM);
        spr_main1.drawNumber(mode5_Temp, 159, 27, 4);
        spr_main1.drawNumber((millis() - mode4Millis) / 1000, 159, 82, 4)    ;
      }
      break;
    case 6:
      if (temp < mode6_Temp) {
        mode = 0;
        M5.Speaker.beep();
        btnAEnable();
      } else {
        spr_main1.drawXBitmap(0, 0, mode5, mode5_width, mode5_height, TFT_RED);
        spr_main1.setTextColor(TFT_RED);
        spr_main1.setTextDatum(TR_DATUM);
        spr_main1.drawNumber(mode6_Temp, 159, 27, 4);
        spr_main1.drawNumber(mode5Millis / 1000, 159, 82, 4)    ;

      }
      break;
  }
  spr_main1.pushSprite(160, 0);
  //Graph
  if (mode != 0) {
    int x = (int)((millis() - totalMillis) / 2000ul) + 20;
    int y = 100 - (temp / 2.5);
    if (y < 0)y = 0;
    if (y > 109)y = 109;
    if (x > 320)x = 320;
    spr_Graph.drawPixel(x, y, TFT_WHITE);
  }
  spr_Graph.pushSprite(0, 110);

  delay(500);
}
```

MCP9600のライブラリGroveのは不安定だったので、Adafruiteのを利用
18bitは不安定だったので16bitに
フィルターは応答が遅くなるので2に

#動作画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/f0ef9777-345d-aff9-bb2e-4317b43a9b30.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/cb66e39c-28f6-bf40-6a1f-ff095aeae379.png)
下の写真はADCのビットが18の時でたまに低めの温度が表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/b95fe5b3-65c4-3f83-b266-b6dc323b6c5c.png)

![231821309_5824427610965918_6063218022892986055_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97061/171f2227-413b-71df-5657-6360b5e80fc3.jpeg)