網頁最後修改時間:2016/12/19
*********************************************************************************
MAX6675 - K 型熱電偶溫度轉換模組可至露天賣場訂購:
整合型 LCD可至露天賣場訂購:
*********************************************************************************
材料列表:
- 1 x pcs [ Arduino 板 ]
任何版本的都可以,程式都是適用的 - 1 x set [ MAX6675 - ( 內附 ) K 型熱電偶 ( Thermometer ) 溫度轉換模組 ]
- 1 x set [ {5V}整合型{ 4/8BIT,IIC,4SPI }1602英文字型LCD螢幕 (附排針與可變電阻,16x2,藍底白色,LED背光)-可用於Arduino,單晶片,8051,AVR) ]
上面的材料中沒有列出佈線所使用的杜邦線和小麵包板,請自己根據手邊現有材料自己變通使用!
佈線電路圖:
K 型熱電偶溫度讀取,周邊接線圖 |
MAX6675 K 型熱電偶溫度讀取接線示意圖 |
MAX6675 使用 SPI ( Serial Peripheral Interface, 串列周邊介面 ) 通訊的方式來與微處理器做溝通,但是實際上它只用唯讀模式,也就是微處理器只要負責讀取就好!
看下圖。當 /CS 由高準位變化為低準位,形成降緣觸發 ( Falling edge-trigger ) 後,就可以開始讀取 16 個 bit 的資料。
讀取時,要傳送 SCK ( 時脈 ) 的訊號。每一個時脈,會讓 MAX6675 知道,將數據依順序由高位元 ( D15 ) 至低位元 ( D0 ) 的方式放置在 SO 接腳,等待微處理器讀取,直到全部讀取完畢。最後再將 /CS 切回高準位,關閉晶片。
MAX6755 - Serial Interface Protocol, source: max6675 datasheet, page 6 |
使用者還要注意一點!若是使用的微處理器的速度很快 ( 單一指令處理的速度快於 100 ns ( 100 * 10-9 秒 ) ),就必須考慮到在程式碼中加入延遲時間,避免資料讀取錯誤。( 這部分請參考下方程式碼中;購買者可直接上雲端硬碟下載完整程式碼 )
MAX6675 - Serial Interface Timing, source: max6675 datassheet, page 3 and 6 |
讀取的數據共有 16 個 bit ( 2 bytes ),除了 bit 3 - 14 ( 溫度數據 ) 和 bit 2 ( TC 狀態 ) 需要考慮之外,其他的 bit 讀取之後就可以不去管它。
bit 2:此 bit 為 1,表示 TC 開路,需要檢查;為 0 表示正常。
bit 3 - 14:12-bit 的溫度數據,但因為包含小數點 ( 0.25 ℃ 溫度解析度 ),所以取得的數據必須再除以 4 才是真正的 K 型熱電偶所偵測到的溫度。溫度範圍在 0 - 1023.75 ℃。
程式碼:
Arduino IDE 版本:使用 V1.5.8, V1.6.4 測試。
程式碼以去除掉一些註解,所以行號不一定會連續。
Arduino 的程式主要分成兩個部分:
- 整合型 LCD @ I2C 模式下的控制程式
因為不一定使用者使用的 LCD 與網頁中一樣,因此在程式開頭處可以取消這個裝置的操作,加入自己的 LCD 控制程式碼。 - K 型熱電偶 MAX6675 模組讀取溫度的程式碼
使用 SPI 通訊的方式來做讀取。
程式中的所有的輸出,都會由串列埠輸出以及顯示在整合型 LCD 上,可直接使用 Arduino IDE 的 Serial Monitor 觀看輸出情形。
* 變數設定
line 14:不使用整合型 LCD,則直接在此行前面加上 // 雙斜線取消掉。
line 19 - 21:定義 MAX6675 SPI 通訊使用的接腳。
* setup()* 變數設定
11 #include <stdio.h>
12 #include <Wire.h> // I2C library for I2C LCD
13
14 #define USEI2CLCD // 不使用就在前面加 //
15 #ifdef USEI2CLCD
16 #define ADDRI2CLCD 0x3C
17 #endif
18
19 #define _SCK 4
20 #define _CS 2
21 #define _SO 6
22 static volatile uint8_t is_tc_open;
line 14:不使用整合型 LCD,則直接在此行前面加上 // 雙斜線取消掉。
line 19 - 21:定義 MAX6675 SPI 通訊使用的接腳。
150 void setup() {
151 Serial.begin(9600); // debug output
152 Wire.begin();
153 max6675_init();
154 Serial.println( "MAX6675 Ready !" );
155
156 #ifdef USEI2CLCD
157 initLCD();
158 delay(100);
159 clearLCD();
160 delay(100);
161 displayCharOnLCD( 1, 1, "MAX6675 Ready ! ", 16 );
162 #endif
163 }
line 151:Arduino 串列埠初始化;此埠當作除錯用。
line 152:I2C 函式庫初始化;沒使用整合型 LCD 可以將這行前面加 // 雙斜線取消掉。
line 153:MAX6675 接腳初始化。
83 void max6675_init()
84 {
85 pinMode( _SCK, OUTPUT );
86 pinMode( _SO, INPUT );
87 pinMode( _CS, OUTPUT );
88
89 digitalWrite( _CS, HIGH );
90 }
line 154:串列埠輸出"準備好"的提示文字
line 156 - 162:如果有使用整合型 LCD,初始化 LCD、清除螢幕文字、最後顯示"準備好"的提示文字在螢幕上。
* loop()
165 void loop() {
166 // 確認 TC 是否開路或是故障
167 if( is_tc_open )
168 {
169 static uint8_t tc_check;
170 Serial.println( "TC is Open !");
171 #ifdef USEI2CLCD
172 displayCharOnLCD( 1, 1, " TC is Open ! ", 16 );
173 displayCharOnLCD( 2, 1, " ", 16 );
174 char a = 0x35 - (char)tc_check;
175 displayCharOnLCD( 2, 8, &a , 1 );
176 #endif
177
178 // 每 5 秒鐘重新確認 TC 是否已重新連接上
179 if( tc_check ++ > 3 )
180 {
181 max6675_getCelsius();
182 tc_check = 0;
183 }
184 }
185 else
186 {
187 float C = max6675_getCelsius();
188 float F = max6675_getFahrenheit();
189 Serial.print( C );
190 Serial.println(" C");
191 Serial.print( F );
192 Serial.println(" F");
193 #ifdef USEI2CLCD
194 char buf[17];
195 uint16_t number;
196 uint8_t fractional;
197 number = (int)C;
198 fractional = ( C - (float)number ) * 100;
199 sprintf(buf, "%4d.%2d C ", number, fractional );
200 displayCharOnLCD( 1, 1, buf, 16);
201 number = (int)F;
202 fractional = ( F - (float)number ) * 100;
203 sprintf(buf, "%4d.%2d F ", number, fractional );
204 displayCharOnLCD( 2, 1, buf, 16);
205 #endif
206 }
207 delay(1000);
208 }
loop() 一開始就會先檢查 TC 是否開路,但因為 is_tc_open 設定為全局靜態變數,所以條件不會成真,開電後第一次會直接從 line 185 開始執行。
line 207:延遲 1 秒。每隔 1 秒鐘讀取一次 MAX6675 資料。
line 167 - 184:TC 開路偵測以及處理。只要取回來的數據中 bit 2 為 1,就會將 "TC is open !" 的文字訊息送到串列埠以及 LCD 螢幕上;使用者可以有 5 秒鐘的時間處理 TC 開路的問題,時間會以倒數的方式顯示在 LCD 螢幕的第 2 行,然後再讀取一次 MAX6675 的數據,判斷是否已恢復正常。
line 185 - 206:讀取 MAX6675 的攝氏 ( ℃ ) 和華氏 ( °F )的溫度,並將數值由串列埠輸出和顯示在 LCD 螢幕上。如果不使用整合型 LCD,則 line 193 - 205 之間的程式碼不會執行。
* max6675_getFahrenheit()
139float max6675_getFahrenheit()
140 {
141 float f = max6675_getCelsius();
142 if( f != NAN )
143 {
144 return ( f * 9.0/5.0 + 32.0 );
145 }
146 else
147 return NAN;
148 }
讀取 MAX6675 的計算之後是攝氏 ºC,要使用華氏 ºF 必須先讀取華氏溫度後再經公式做轉換。如果取得的溫度是有效的 ( line 142 ) 就直接回傳計算之後華氏的溫度值;不然就傳回 NaN ( line 147 )。
* max6675_getCelsius()
92 float max6675_getCelsius()
93 {
94 uint16_t t_c = 0;
95
96 //初始化溫度轉換
97 digitalWrite( _CS, LOW );
98 delay(2);
99 digitalWrite( _CS, HIGH );
100 delay(220);
101
102 // 開始溫度轉換
103 digitalWrite( _CS, LOW );
104
105 // 15th-bit, dummy bit
106 digitalWrite( _SCK, HIGH );
107 delay(1);
108 digitalWrite( _SCK, LOW );
109
110 // 14th - 4th bits, temperature valuw
111 for( int i = 11; i >= 0; i-- )
112 {
113 digitalWrite( _SCK, HIGH );
114 t_c += digitalRead( _SO ) << i;
115 digitalWrite( _SCK, LOW );
116 }
117
118 // 3th bit, 此位元可以用來判斷 TC 是否損壞或是開路
119 // Bit D2 is normally low and goes high when the therometer input is open.
120 digitalWrite( _SCK , HIGH );
121 is_tc_open = digitalRead( _SO );
122 digitalWrite( _SCK, LOW );
123
124 // 2nd - 1st bits,
125 // D1 is low to provide a device ID for the MAX6675 and bit D0 is three-state.
126 for( int i = 1; i >= 0; i-- )
127 {
128 digitalWrite( _SCK, HIGH );
129 delay(1);
130 digitalWrite( _SCK, LOW );
131 }
132
133 // 關閉 MAX6675
134 digitalWrite( _CS, HIGH );
135
136 return (float)(t_c * 0.25);
137 }
line 96 - 103:讓 /CS 的狀態維持在高準位,然後進入低準位形成降緣觸發。此時微處理器可以開始接收資料。
line 105 - 131:16 個 bit 的接收。bit 15 沒有用處,直接以一個時脈訊號帶過 ( line 106 - 108 ),加個 1 ms 的延遲,避免時脈速度太快 ( 這在之前有解釋過為什麼要加延遲 )。
緊接著,接收 12 個 bit ( bit 14 - 3 ) 溫度資料,然後將數據暫時存放在 t_c 變數中。
再來接收 bit 2 單個 bit 的資料,將其存放在全局變數 is_tc_open 變數中。最後之接傳送兩個時脈訊號出去 ( line 126 - 131 ),結束整個數據讀取的流程,關閉 MAX6675 的通訊 ( line 134 )。
將溫度資料乘以 0.25 ( 除以 4 ) 後回傳,這就是實際的攝氏溫度讀值。
* 整合型 LCD 的功能函式
如果有使用整合型 LCD,下面就是所使用的函式宣告與實作程式碼。
27 #ifdef USEI2CLCD
28 void initLCD()
29 {
30 Wire.beginTransmission(ADDRI2CLCD);
31 Wire.write( 0x00 ); // N x commands
32 Wire.write( 0x38 ); // Function set
33 Wire.write( 0x0C ); // Display ON/OFF
34 Wire.write( 0x01 ); // Clear display
35 Wire.write( 0x06 ); // Entry mode set
36 Wire.endTransmission();
37 }
38
39 void clearLCD()
40 {
41
42 Wire.beginTransmission(ADDRI2CLCD);
43
44 Wire.write( 0x80 ); // One command
45 Wire.write( 0x01 ); // Clear display
46
47 Wire.endTransmission();
48 }
49
50 void displayCharOnLCD( int line, int column, const char *dp, unsigned char len )
51 {
52 unsigned char i;
53
54 Wire.beginTransmission(ADDRI2CLCD);
55
56 Wire.write( 0x80 );
57 Wire.write( 0x80 + ( line - 1 ) * 0x40 + ( column - 1 ) );
58 Wire.write( 0x40 );
59
60 for( i = 0; i < len; i++)
61 {
62 Wire.write( *dp++ );
63 }
64
65 Wire.endTransmission();
66 }
67 #endif
只要將上面的程式碼依行號整理一下,就是整個原始碼!使用者只要了解上面所說明的 MAX6675 資料讀取的方式,就可以充分了解程式碼寫作的重點。
程式執行結果:
為了讓溫度提高多一點!點了一根蠟燭並讓 TC 的探頭接近燭光 ( 不用放在上面燒 ),此時就會看到 LCD 螢幕的數值開始往上跑。使用者可以同時打開 Serial Monitor 看輸出的溫度值,與 LCD 螢幕上面所顯示都會是一樣的。
程式執行結果畫面 |
看過上面說明後,可以了解到使用 MAX6675 讀取 K 型熱電偶所偵測的溫度值是非常容易的!如果使用的環境不只是高溫而且還有酸鹼的環境,就可以更換其他有包覆鐵氟龍的 K 外套的 K 型熱電偶,不但防水、防油、防腐蝕、耐酸鹼,而且溫度可量測到 260 ℃。
測溫時,使用者應該要考慮的不只是可量測的溫度高低,還有注意現場環境的裝設難易度還有環境中是否具有酸鹼 ... 等,都是在選用溫度感測器需要考量的因素。
電路佈線圖和程式碼的腳位不同喔
回覆刪除圖上面MAX6675接arduion是2,4,6但程式碼是2,5,8喔!
(因為我剛剛讀不到XDD
哇! 終於有人發現了!
刪除大家應該都自己搞定,懶得跟我講了!
錯誤已經更正,謝謝你的提醒 !