K型熱電対を使用したハンダこて温度計の製作

[公開:any]

[電子工作/AVR]
[電子工作/測定器]
[AVR,ATtiny861A,MAX31855K,測定器]

origin 2015-09-23


 電子工作で使用するハンダは、太洋電機産業(goot)の電子工作用(プリント基板用)のSEシリーズ1kg巻きを小さな小巻リールに巻き替えて使用してきました。半年ほど前にそのハンダがなくなったので、千住金属のスパークルハンダの1kg巻きを購入して使用しています。このハンダは、以前のものと比べてフラックスの蒸発が早くて「濡れ」がいまひとつです。ハンダこて(白光の速熱ボタンつきのプレスト)の温度が高いと作業性が悪いので、こて先をスポンジで冷やしながら作業をしていましたが、かなり面倒です。


 そこで、思い切ってこて先の温度管理が楽なステーションタイプの白光FX-888Dというハンダこてを購入しました。こて先の温度を変えながらハンダのフラックスの蒸発具合を見ていると設定温度が330℃が一番よさそうです。一般的なハンダ付けは350℃前後といわれていますが、かなり低い設定温度となります。こて先の温度設定と実際の温度に誤差があるのじゃないかと気になっていました。

HAKKO FX-888D

 市販のハンダこて温度計は、高価なので安いものがないかネットで調べてみると、白光のK型熱電対センサーを使用するキットが安く販売されています。専用のアンプICとPICをつかったキットになっています。白光のセンサーも10個1000円程度で入手できるので、K型熱電対アンプICを入手すれば簡単にハンダこて先温度計が作成できそうです。

白光 K型熱電対 温度センサー

 K型熱電対アンプICは、MAX31855Kがよく使われているようです。国内でも秋月電子やストロベリーリナックスでモジュールの扱いがあります。今回は、秋月電子でMAX31855使用K型熱電対アンプモジュール を購入しました。MAX31855の標準電源電圧は3.3Vなのですが、このモジュールにはレギュレータが搭載されているので、電源や信号線が5V系で動作するようになっています。マイコンにはAVRのATTiny861A、温度表示には、3桁の7セグメントLEDを使用してブレッドボードでテストしてみました。

MAX31855Kモジュール

 MAX31855とはSPIにより通信を行いますが、読み込みのみで書き込みはないため、通常のポートを利用して温度データのみ取り出しています。CS(LE)をローにしてクロックを32ビット送り、その立下りでデータポートを読むだけです。32ビットのデータを受信して、先頭の14ビットから温度を求めることができます。


 回路図です。7セグメントLEDは、3桁のモジュールになったもので、ダイナミック点灯により動作させます。

ハンダこて温度計回路図

 秋月電子のユニバーサル基板小に実装しました。

ハンダゴテ温度計ハンダゴテ温度計基板

 ケースは秋月電子のプラケース中を使用します。センサーは、ケース外側に10mmのスペーサーを使用してねじ止めできるようにします。この状態でセンサーは空中にあるので周辺の温度の影響が小さくなります。MAX31855モジュールは、ケース内側に取り付けますが、センサーとの距離が20mm程度あるので通常の銅線を使用して接続しました。調べてみると本来なら補償導線という専用のものが必要らしいのですが、モジュールの接続口とセンサーの固定部の温度傾度は小さいため無視することにしました。電源を入れた状態では、室内温度を示しています。

 センサーの熱容量は小さいので、温度変化のレスポンスが良好です。このため表示の変化も早いので最大値保持機能を搭載しました。LED内蔵プッシュスイッチはこの切り替えです。MAX HoldをONにするとLEDが点灯して、測定した最大値を保持します。

ハンダゴテ温度計

 こて先温度を340℃に設定して測定してみると345℃となりました。こて先を330℃に設定すると334℃となるので、こて先の温度は設定にあわせて概ね正しい変化をしています。ただ、温度測定値の校正はできていないので、この温度が正しいのかどうかはわかりません。また、測定のやり方によって大きく値が異なります。いろいろと試した結果は、こて先を濡れスポンジ等できれいにして、薄くハンダを乗せてセンサーにこて先を押し付ける方法がよさそうです。


 以前、使用していた白光のプレストです。速熱ボタンを押さなくても、しばらく置いておくとこて先温度は400℃近くまで上昇します。これでは、温度が高すぎてフラックスがすぐに蒸発し、ハンダの流れが悪くなることがわかります。


 作成したプログラムソースです。AVR Studioで作成しました。また、ソースを見てもらえばわかりますが、今回の用途から正(プラス+)の温度のみに対応しています。なお、7セグメントLEDの接続は、回路図と実際の実装が異なるため、maskルーチンでどのセグメントを点灯させるかを適当に編集する必要があります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>

#define SPI_PORT    PORTB
#define SPI_CLOCK    PB4
#define SPI_LE        PB5
#define SPI_DATA    PB6

#define cbi(addr, bit)     addr &= ~(1<<bit)
#define sbi(addr, bit)     addr |=  (1<<bit)

unsigned int seg[3];
unsigned int mx;
unsigned char mode;        // mode 0: Normal, mode 1: Max Hold

// milisecond order delay
void delay_ms(unsigned int t)
{
    while(t--)
        _delay_ms(1);
}

// Returns mask 7-seg. display
unsigned int mask(unsigned int num) {
    switch (num) {
        case 0 : return 0b01000000;
        case 1 : return 0b01011011;
        case 2 : return 0b00100010;
        case 3 : return 0b00001010;
        case 4 : return 0b00011001;
        case 5 : return 0b00001100;
        case 6 : return 0b00000100;
        case 7 : return 0b01011010;
        case 8 : return 0b00000000;
        case 9 : return 0b00001000;
        case 10 : return 0b00111111;    // -
        case 11 : return 0b00100100;    // E
        case 12 : return 0b00110111;    // r
        case 99 : return 0b01111111;     // space
        default: return 0b01111111;
    }
}

// Timer0 Overflow interrupt
ISR(TIMER0_OVF_vect)
{
    TCNT0L = 64;
    if(mode)
        PORTA = seg[mx] | _BV(PA7);
    else
        PORTA = seg[mx];    
    switch(mx) {
        case 0: cbi(PORTB, PB2); sbi(PORTB, PB1); sbi(PORTB, PB0); break;
        case 1: sbi(PORTB, PB2); sbi(PORTB, PB1); cbi(PORTB, PB0); break; 
        case 2: sbi(PORTB, PB2); cbi(PORTB, PB1); sbi(PORTB, PB0); break;
    }
    mx++;
    if(mx > 2)
        mx = 0;
}

int spi_readtemp()
{
    unsigned int i, j;
    long dat;
    
    cbi(SPI_PORT, SPI_LE);
    for(i = 0; i < 32; i++) {
        dat <<= 1;
        if(bit_is_set(PINB, SPI_DATA))
            dat |= 1;
        sbi(SPI_PORT, SPI_CLOCK);
        cbi(SPI_PORT, SPI_CLOCK);
    }
    sbi(SPI_PORT, SPI_LE);
    
    dat = dat >> 18;
    return (int)(dat * 0.25 + 0.5);
}

int main(void)
{
    unsigned int i;
    unsigned char sw_state;
    int tem, max;

    DDRA = 0b11111111;        // PA0-6 7seg cathode
    DDRB = 0b10110111;        // PB4-6 MAX31855K SPI
    PORTB = 0b00001000;        // PA7 SW input Pull up

    TCNT0L = 64;                 // Timer0 counter set
    TCCR0A= 0;                // Timer0 standard timer mode                
    TCCR0B= 4;                // Timer0 Prescaler 1/256
    TIMSK = _BV(TOIE0);        // Timer0 Overflow Interrupt Enable

    delay_ms(200);
    sw_state = 0;
    mode = 0;
    max = 0;

    sei();

    while(1) {
        
        tem = spi_readtemp();
        
        if(max < tem)
            max = tem;
        
        if(mode)
            tem = max;
        
        if(tem > 999 || tem < -99) {
            seg[0] = mask(11);
            seg[1] = mask(12);
            seg[2] = mask(12);
        } else {
            if(tem < 0) {
                seg[0] = mask(10);
            } else {
                i = (tem / 100) % 10;
                if(i == 0)
                    i = 99;
                seg[0] = mask(i);
            }
            i = abs((tem / 10) % 10);
            seg[1] = mask(i);
            i = abs(tem % 10);
            seg[2] = mask(i);
        }
        
        if(bit_is_clear(PINB, PB3)) {
            sw_state = 1;
            delay_ms(15);
        }
        if(sw_state && bit_is_set(PINB, PB3)) {
            sw_state = 0;
            if(mode) {
                mode = 0;
            } else {
                mode = 1;
                max = 0;
            }            
        }
        delay_ms(20);
    }
}

▲ページ Top へ...