「以前はホットプレートで試作基板のリフローをしていた私ですが、最近ではオーブントースターでリフローしています」
今回はそんなお話です。
スイッチサイエンスでは、試作基板ができたら紙マスク(メタルマスクの紙版)を使ってペーストハンダを塗り、ピンセットで部品を搭載し、オーブントースターをハックしたリフローオーブンで試作品を作っています。
内容には当社が行った「家電の改造行為」が含まれています、実際の改造は各自の責任において行ってください。
オーブントースターは「PANASONIC NT-W50-S」を選びました。
#ホットプレートのように下からだけの加熱ではなく、上下に熱線(ヒーター)が付いているので両面からの加熱が可能
#上下あわせて1300Wの火力がステキ
このオーブントースターをハックする回路を作りました。
仕組みとしては「Arduino Uno R3」に「K型熱電対温度センサモジュールキット(SPI接続)MAX31855使用」を接続してSSR(ソリッド・ステート・リレー)にてヒーターをコントロールし、LCDディスプレイに状態を表示している感じです。
上記組み合わせをバニラシールド上に作って使いはじめましたが、先の事を考えると「頻繁に使うものなので基板を起こそう!欲しい人には売ってあげよう!」という事になりました。
これは試作機
#SSRにはヒートシンクも付けました
#ケースは「FabLabつくば」で作っていただきました
こちらが製品版(発売開始しました! リフロートースターコントローラーキット)
こちら「FTDI USBシリアル変換アダプター(5V/3.3V切り替え機能付き)」を3.3Vに設定してArduinoIDEから直接プログラムが書き込めます。
#マイコンボードは「Arduino Pro or Pro Mini (3.3V,8MHz) w/ATMega328」をお選び下さい
SSRは、以下の2種類を試してみました。
CrydomのD2425(3~32VDCにて24~280VACの25Aまでの制御が可能)
CrydomのCL240D10(3~32VDCにて240VACの10Aまでが制御可能)
どちらも問題なく動作しています。
実際に焼いてみると匂いが気になったので、ケース(手元にあった段ボール箱)とシロッコファン、排気ダクト、排気口なんかを設置してみました。
オーブントースターのハックはこんな感じです。
1.外装を開けるため、裏側のネジを7本外します(写真の赤ポチ部分)。
2.外装を開けるため、下側のネジを5本外します(写真の赤ポチ部分、4本は足の中に埋め込まれています)。
3.外装を開けるため、正面のネジを6本外します(写真の赤ポチ部分、外さなくても大丈夫かも)。
4.赤丸の部分(2箇所)をハックします!
それぞれの赤丸部分に繋がっている線を外して、それぞれSSRに割り込ませます。
#ここには耐熱ケーブルを使う事をオススメします。
5.外装を加工してケーブルを出します。
とりあえず棒を突っ込んでフィン部分をめくっただけです。
温度センサの先端が基板に近い位置(特に高さ)に来るようにするといいでしょう。
いかがでしょう、皆さんも自宅でリフローにチャレンジしてみませんか?!
スイッチサイエンスで使っているリフローのスケッチを以下に掲載します。
こちらを改造して使うと簡単でしょう。
githubにもあります。Dual_SSR_Solder_Toaster_Controller_Platform
スケッチ冒頭にある「temprature_control_data[ControlDataLen + 1][3]」内のデータを編集して「#define ControlDataLen 3」この数値を作ったデータの行数に変更すれば上下ヒーターのコントロールや時間、温度の変更ができますね。
#define allOFF 0 #define upON 1 #define downON 2 #define allON 3 #define ControlDataLen 3 int temperature_control_data[ControlDataLen + 1][3] = { {downON, 130, 15}, // 2ON , temperature130, keep15sec {allON , 230, 0}, // 1&2ON , temperature230, keep0sec {downON, 225,100}, // 2ON , temperature225, keep100sec {allOFF, 0, 0} // 1&2OFF, temperature0 , keep0sec }; #include <LiquidCrystal.h> #include <SPI.h> // LCD(D2-D7) #define LCDrsPin 2 #define LCDenablePin 3 #define LCDd4Pin 4 #define LCDd5Pin 5 #define LCDd6Pin 6 #define LCDd7Pin 7 // button(D8) #define StartButton 8 // Beep(D9) #define TonePin 9 // Tempratier(D10,D12-D13) #define TemperatureSlavePin 10 #define TemperatureMisoPin 12 #define TemperatureSckPin 13 // PowerControl(A0,A1) #define Heat1Pin 14 #define Heat2Pin 15 LiquidCrystal lcd(LCDrsPin,LCDenablePin,LCDd4Pin,LCDd5Pin,LCDd6Pin,LCDd7Pin); #define delayWait 100 #define oneSec (1000 / delayWait) byte state; // main program mode byte heatMode; // UpDown heater mode byte heatState; // UpDown heater status byte tableCounter; // data table counter int temperatureWait; // temprature keep time(SEC) float temperature; // Temperature float temperatureMax; // target Temprature int blinkTimer; // blink timer boolean blinkFlag; // blink ON/OFF flag void setup() { // degug Initialize(SerialMonitor) Serial.begin(9600); // LCD initialize lcd.begin(20, 4); // button initialize pinMode(StartButton, INPUT_PULLUP); // PowerControl initialize pinMode(Heat1Pin, OUTPUT); pinMode(Heat2Pin, OUTPUT); // Temprature initialize pinMode(TemperatureSlavePin, OUTPUT); digitalWrite(TemperatureSlavePin, HIGH); SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setClockDivider(SPI_CLOCK_DIV4); SPI.setDataMode(SPI_MODE0); // memory initialize state = 0; } void loop() { tempratureRead(); switch (state) { case 0: // initialize lcd.clear(); heatMode = 0; temperatureMax = 0; tableCounter = 0; state++; break; case 1: // start switch wait if (digitalRead(StartButton) == LOW) { tone(TonePin,600,800); // StartSound lcd.clear(); setTempratureData(); state++; } break; case 2: // target Temperature if (temperatureMax <= temperature) { state++; } break; case 3: // keep time if (--temperatureWait <= 0) { state++; } break; case 4: // Loop or Finish? tableCounter++; setTempratureData(); if (tableCounter < ControlDataLen) { state = 2; } else { tone(TonePin,600,1500); // FinishSound state++; } break; case 5: // finish switch wait if (digitalRead(StartButton) == LOW) { state = 0; } break; } heatControl(); lcdDisplay(); delay(delayWait); } void setTempratureData() { heatMode = temperature_control_data[tableCounter][0]; temperatureMax = temperature_control_data[tableCounter][1]; temperatureWait = temperature_control_data[tableCounter][2] * oneSec; heatState = heatMode; } void tempratureRead() { unsigned int thermocouple; unsigned int internal; float disp; // read tem digitalWrite(TemperatureSlavePin, LOW); thermocouple = (unsigned int)SPI.transfer(0x00) << 8; thermocouple |= (unsigned int)SPI.transfer(0x00); internal = (unsigned int)SPI.transfer(0x00) << 8; internal |= (unsigned int)SPI.transfer(0x00); digitalWrite(TemperatureSlavePin, HIGH); if ((thermocouple & 0x0001) != 0) { Serial.print("ERROR: "); if ((internal & 0x0004) !=0) { Serial.print("Short to Vcc, "); } if ((internal & 0x0002) !=0) { Serial.print("Short to GND, "); } if ((internal & 0x0001) !=0) { Serial.print("Open Circuit, "); } Serial.println(); } else { if ((thermocouple & 0x8000) == 0) { temperature = (thermocouple >> 2) * 0.25; } else { temperature = (0x3fff - (thermocouple >> 2) + 1) * -0.25; } } } void heatControl() { if (temperature > temperatureMax) { heatState = 0; } else if (temperature < (temperatureMax - 0.5)) { heatState = heatMode; } if ((heatState & 1) == 0) { digitalWrite(Heat1Pin, LOW); } else { digitalWrite(Heat1Pin, HIGH); } if ((heatState & 2) == 0) { digitalWrite(Heat2Pin, LOW); } else { digitalWrite(Heat2Pin, HIGH); } } void lcdDisplay() { lcd.setCursor(3, 0); lcd.print("STATUS:"); switch (state) { case 0: // initialize case 1: // start switch wait lcd.print("-------"); lcd.setCursor(1, 1); if (blinkFlag == true) { lcd.print("press START button"); } else { lcd.print(" "); } lcd.setCursor(3, 3); lcd.print("SWITCH SCIENCE"); break; case 2: // target Temperature case 3: // keep time case 4: // Loop or Finish? case 5: // finish switch wait if (state != 5) { if (blinkFlag == true) { lcd.print("RUNNING"); } else { lcd.print(" "); } } else { lcd.print("FINISH!"); } lcd.setCursor(0, 1); if ((heatState & 1) == 0) { lcd.print("HEAT1:OFF "); } else { lcd.print("HEAT1:ON "); } if ((heatState & 2) == 0) { lcd.print("HEAT2:OFF"); } else { lcd.print("HEAT2:ON "); } lcd.setCursor(5, 3); lcd.print("WAIT:"); if (state == 3) { lcd.print(temperatureWait / oneSec); lcd.print("."); lcd.print(temperatureWait % oneSec * 10 / oneSec); lcd.print("sec"); } else { lcd.print("---.- "); } lcd.print(" "); break; } lcd.setCursor(2, 2); if (temperature < 100.0) lcd.print(" "); if (temperature < 10.0) lcd.print(" "); lcd.print(temperature); lcd.print(" / "); lcd.print(temperatureMax); lcd.print(" "); // blink control if (++blinkTimer >= oneSec) { blinkTimer = 0; if (blinkFlag == false) { blinkFlag = true; } else { blinkFlag = false; } } }