自作リフロー装置の製作 (Raspberry Pi とオーブントースター)

最近電子工作に挑戦し始め Kicad で基板設計をやっているのですが、基板の小型化のために SMD(表面実装部品)を使いたくなりました。
上手な人は SMD でも手はんだできるみたいですが、私にはハードルが高くて断念せざるをえませんでした。
後々まとまった数の基板を作りたいとも思っていたので、リフロー装置を自作してみることにしました。
自作のリフロー装置については「ホームリフロー」とか「自作リフロー装置」で調べるとたくさん作例がでてきます。
Maker の間では基本装備みたいなものなんですね。

パーツリスト

部品は以下の物を使いました。

Table 1: パーツリスト
名称 個数 購入先
TIGER オーブントースター やきたて ぷちはこ 1 Amazon
Raspberry PI B+ 1 秋月
MAX31855 使用 K 型熱電対アンプモジュール 1 秋月
K 型熱電対プローブ 1 秋月
ユニバーサル基板 1 秋月
ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプ 2 秋月
ピンヘッダ 2 × 20(40P) 1 秋月
2 x 20(40P)両端コネクタ付 IDC リボンケーブル 1 秋月
テフロン線 0.3SQ 1 マルツ
耐熱電子ワイヤー 2m × 7 色 1 秋月
その他(プラ足、M3 ねじ、カプトンテープ等) 適宜 秋月

Raspberry PI B+は以前に買って使っていなかったものがあったのを使用しました。
Pi 2 を使っても問題ないはずです。

トースターは置き場所もあまりないので小型のものにしました。
余裕があればファンが付いたものがいいかも。

SSR は定格電流が大きく、作例も多かった秋月のキットにしました。
トースターは上下にヒーターがあり、それぞれを制御できるように SSR を二つ使いましたが、一つで十分だったかもしれません。

かなり簡単な回路なのでユニバーサル基板ではなく小さめのブレッドボードでも良いと思います。

配線は耐熱温度が高いものを選びましょう。

製作

トースター

まずはトースターの背後と底面ででねじ止めされている外装を外します。
下図のようヒーターに繋がるケーブルを外し、SSR を割り込ませます。
圧着端子やラグ端子があると配線がしやすいです。
今回 SSR をスリットを利用してねじ止めしてしましたが、よく考えたら SSR の耐熱温度がわからないので SSR は外に出した方がいいかもしれません。
今の所不具合は起きていませんが劣化が早いかも。最後に外装を元に戻しておきます。
あと電源を入れるのにダイヤルを回すのも面倒なのでスイッチに置き換えたり、ベルは外してもいいかもしれません

oven_inner.png

Figure 1: オーブントースターの配線

基板

Raspberry Pi にアンプを接続します。Adafruit のメーカーページ にアンプを Raspberry Pi で使用する際のマニュアルがあります。ここ の Hardware SPI の通りに接続します。熱電対はコネクタケーズを分解しアンプに接続します。

後はフラットケーブルを Raspberry Pi に接続し、適当な GPIO に SSR を接続します。今回はヒューズとか保護回路は付けてませんが、できれば付けた方がいいです。

PCB_151006.png

Figure 2: 基板

プログラム

まずは Raspberry Pi に OS などの基本的な設定をし、Python で GPIO を操作できるようにしておきます。
次に ここ からアンプ用のライブラリをダウンロードしてインストールします。
Raspian なら Python はインストールされているはずです。
Python3 で使う場合は sudo python3 setup.py install とします。

制御プログラムは以下のようなものを作りました。
Python3 で書いてるのでターミナルから sudo python3 main.py として実行します。
測定中は目標値等を表示するようにし、測定データは csv 形式で保存するようにしています。

PID 制御のクラスは ここ から拝借しました。
本来はオーブンの熱容量とか放熱量をモデル化するといいんでしょうけど、適当に制御パラメータを設定しただけでも問題なくリフローできました。
まあ鉛入りはんだでしか試してないので問題が起きてないだけかも知れないので、問題が起きればちゃんと制御系を作ります。

ちなみに制御パラメータの設定は応答の遅い系では限界感度法等ではうまくいきにくいです。
そこでパラメータは簡単にトライアンドエラーで調整しました。
まず目標温度を 180 ℃あたりにして P だけでオーバーシュートしない程度の値を探します。
次に序々に I を上げていき偏差が小くなるようにし、最後に D を加えるのと P と I の微調整をしました。

温度プロファイルは適当に検索するといっぱい出てきます。
それらを参考にトースターの性能に合わて微調整してものを設定しました。

# coding: utf-8
import RPi.GPIO as GPIO
import time
import csv
import Adafruit_GPIO.SPI as SPI
import Adafruit_MAX31855.MAX31855 as MAX31855

GPIO.cleanup()

# SSR 操作の GPIO 設定
# 上:16, 下:18
PIN1 = 16
PIN2 = 18
GPIO.setmode(GPIO.BOARD)
GPIO.setup(PIN1, GPIO.OUT)
GPIO.setup(PIN2, GPIO.OUT)
p1 = GPIO.PWM(PIN1, 50)
p2 = GPIO.PWM(PIN2, 50)
p1.start(0.0)
p2.start(0.0)

# Raspberry Pi のハードウェア SPI 設定
SPI_PORT = 0
SPI_DEVICE = 0
sensor = MAX31855.MAX31855(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))

# 温度プロファイル、PID 制御パラメータ設定()
# 外気温 26 ℃
sp = [[120.0, 60],
      [170.0, 110],
      [225.0, 150],
      [0.0, 210]]               # 目標値(℃), 終了時刻(s)を設定
Kp = 2.0
Ki = 0.06
Kd = 1.0

# 制御間隔(s)
delay_time = 0.1


# PID 制御のクラス
class PID:
    def __init__(self, P=2.0, I=0.0, D=1.0, Derivator=0, Integrator=0, Integrator_max=500, Integrator_min=-500):
	self.Kp = P
	self.Ki = I
	self.Kd = D
	self.Derivator = Derivator
	self.Integrator = Integrator
	self.Integrator_max = Integrator_max
	self.Integrator_min = Integrator_min
	self.set_point = 0.0
	self.error = 0.0

    def update(self, current_value):
	self.error = self.set_point - current_value

	self.P_value = self.Kp * self.error

	self.D_value = self.Kd * (self.error - self.Derivator)
	self.Derivator = self.error

	self.Integrator = self.Integrator + self.error

	if self.Integrator > self.Integrator_max:
	    self.Integrator = self.Integrator_max
	elif self.Integrator < self.Integrator_min:
	    self.Integrator = self.Integrator_min

	self.I_value = self.Integrator * self.Ki

	PID = self.P_value + self.I_value + self.D_value
	return PID

    def setPoint(self, set_point):
	self.set_point = set_point

    def setIntegrator(self, Integrator):
	self.Integrator = Integrator

    def setDerivator(self, Derivator):
	self.Derivator = Derivator

    def setKp(self, P):
	self.Kp = P

    def setKi(self, I):
	self.Ki = I

    def setKd(self, D):
	self.Kd = D

    def getPoint(self):
	return self.set_point

    def getError(self):
	return self.error

    def getIntegrator(self):
	return self.Integrator

    def getDerivator(self):
	return self.Derivator


def control(p):
    pid.setPoint(p)

    current_temp = sensor.readTempC()
    internal = sensor.readInternalC()
    mv = pid.update(current_temp)

    if mv >= 100:
	mv = 100
    elif mv <= 0:
	mv = 0

    p1.ChangeDutyCycle(mv)
    p2.ChangeDutyCycle(mv)

    print("target:", pid.getPoint())  
    print("current:", current_temp)
    print("internal:", internal)
    print("mv:", mv)

    w.writerow([time.time(), current_temp, internal, mv])

    time.sleep(delay_time)


try:
    pid = PID()
    pid.setKp(Kp)
    pid.setKi(Ki)
    pid.setKd(Kd)

    f = open('data.csv', 'w')
    w = csv.writer(f)

    t0 = time.time()
    timeout1 = t0 + sp[0][1]
    timeout2 = t0 + sp[1][1]
    timeout3 = t0 + sp[2][1]
    timeout4 = t0 + sp[3][1]

    while True:
	if time.time() < timeout1:
	    print("\nPhase1")            
	    control(sp[0][0])
	elif time.time() < timeout2:
	    print("\nPhase2")                        
	    control(sp[1][0])
	elif time.time() < timeout3:
	    print("\nPhase3")                                    
	    control(sp[2][0])
	elif time.time() < timeout4:
	    print("\nPhase4")                                    
	    control(sp[3][0])
	else:
	    break

except KeyboardInterrupt:
    print("detect key interrupt\n")


GPIO.cleanup()
f.close()
print("Program exit\n")

テスト

適当な QFN パッケージの IC と aitendo のピッチ変換基板でテストしました{電子工作}QFN パッケージのハンダ付けについて を参考にさせて頂きました。
クリームはんだはサンハヤトの SMX-H05 を使いました。
マスクがないので爪楊枝等で大雑把に盛ったため盛大にブリッジしました。
吸い取り線でブリッジを修正してみると問題なくはんだが付いていました。
IC の位置もはんだの表面張力で適切な位置に動いたようで問題ありませんでした(写真が悪くてダメですね。ちゃんとカメラ買おう。。。)

result_before_151006.png

Figure 3: はんだ付け結果(ブリッジ修正前)

result_after_151006.png

Figure 4: はんだ付け結果(ブリッジ修正後)

最後に測定データを示します。
ちゃんど温度が制御できています。
鉛入りはんだだともう少し温度が低い方が良いですね。
また、最後の加熱はもっと一気に加熱した方が良さそうです。
鉛フリーはんだでテストする時にでも調整しようと思います。

# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt

t, y, internal, mv = np.loadtxt("data.csv", unpack=True, delimiter=",")

plt.figure()
plt.plot(t-t[0], y)
plt.xlim([0, max(t-t[0])])
plt.xlabel("Time[s]")
plt.ylabel("Temperature[C]")
plt.grid()
plt.show()

reflow_result.png

Figure 5: 温度測定結果

コメント

Comments powered by Disqus
書籍更新情報
2016-10-21
Pythonによる科学技術計算 基礎編
PDF版の販売を開始しました。
販売ページはこちら

2016-09-09
Pythonによる科学技術計算 基礎編
1.2版への更新が可能になりました。
サポートページはこちら
電子書籍
Pythonによる科学技術計算 基礎編
Kindle ストア、Leanpubで販売中です
Pythonによる科学技術計算 基礎編
PDF版の販売はこちら
同人誌
技術書典(2016/6/25)
Emacs/org-modeのPDF作成術
電子版をBOOTHで販売中です
Emacs/org-modeのPDF作成術
Share