Library for MAX31850 thermocouple temperature sensor
Embed:
(wiki syntax)
Show/hide line numbers
MAX31850.cpp
00001 #include "MAX31850.h" 00002 00003 Serial pc(USBTX, USBRX); 00004 00005 #define ONEWIRE_INPUT(pin) pin->input() 00006 #define ONEWIRE_OUTPUT(pin) pin->output() 00007 #define ONEWIRE_INIT(pin) 00008 00009 LinkedList<node> MAX31850::probes; 00010 00011 00012 MAX31850::MAX31850 (PinName data_pin, PinName power_pin, bool power_polarity) : _datapin(data_pin), _parasitepin(power_pin) { 00013 int byte_counter; 00014 _power_polarity = power_polarity; 00015 00016 _power_mosfet = power_pin != NC; 00017 00018 for(byte_counter=0;byte_counter<9;byte_counter++) 00019 scratchpad[byte_counter] = 0x00; 00020 00021 ONEWIRE_INIT((&_datapin)); 00022 00023 if (!unassignedProbe(&_datapin, _ROM)) 00024 error("No unassigned MAX31850 found!\n"); 00025 else { 00026 _datapin.input(); 00027 probes.append(this); 00028 _parasite_power = false; //only set up to use external power right now 00029 } 00030 } 00031 00032 MAX31850::~MAX31850 (void) { 00033 node *tmp; 00034 for(int i=1; i<=probes.length(); i++) 00035 { 00036 tmp = probes.pop(i); 00037 if (tmp->data == this) 00038 probes.remove(i); 00039 } 00040 } 00041 00042 00043 bool MAX31850::onewire_reset(DigitalInOut *pin) { 00044 // This will return false if no devices are present on the data bus 00045 bool presence=false; 00046 ONEWIRE_OUTPUT(pin); 00047 pin->write(0); // bring low for 500 us 00048 wait_us(500); 00049 ONEWIRE_INPUT(pin); // let the data line float high 00050 wait_us(90); // wait 90us 00051 if (pin->read()==0) // see if any devices are pulling the data line low 00052 presence=true; 00053 wait_us(410); 00054 return presence; 00055 } 00056 00057 void MAX31850::onewire_bit_out (DigitalInOut *pin, bool bit_data) { 00058 ONEWIRE_OUTPUT(pin); 00059 pin->write(0); 00060 wait_us(3); // DXP modified from 5 00061 if (bit_data) { 00062 pin->write(1); // bring data line high 00063 wait_us(55); 00064 } else { 00065 wait_us(55); // keep data line low 00066 pin->write(1); 00067 wait_us(10); // DXP added to allow bus to float high before next bit_out 00068 } 00069 } 00070 00071 void MAX31850::onewire_byte_out(char data) { // output data character (least sig bit first). 00072 int n; 00073 for (n=0; n<8; n++) { 00074 onewire_bit_out(&this->_datapin, data & 0x01); 00075 data = data >> 1; // now the next bit is in the least sig bit position. 00076 } 00077 } 00078 00079 bool MAX31850::onewire_bit_in(DigitalInOut *pin) { 00080 bool answer; 00081 ONEWIRE_OUTPUT(pin); 00082 pin->write(0); 00083 wait_us(3); // DXP modified from 5 00084 ONEWIRE_INPUT(pin); 00085 wait_us(10); // DXP modified from 5 00086 answer = pin->read(); 00087 wait_us(45); // DXP modified from 50 00088 return answer; 00089 } 00090 00091 char MAX31850::onewire_byte_in() { // read byte, least sig byte first 00092 char answer = 0x00; 00093 int i; 00094 for (i=0; i<8; i++) { 00095 answer = answer >> 1; // shift over to make room for the next bit 00096 if (onewire_bit_in(&this->_datapin)) 00097 answer = answer | 0x80; // if the data port is high, make this bit a 1 00098 } 00099 return answer; 00100 } 00101 00102 bool MAX31850::unassignedProbe(PinName pin) { 00103 DigitalInOut _pin(pin); 00104 ONEWIRE_INIT((&_pin)); 00105 char ROM_address[8]; 00106 return search_ROM_routine(&_pin, 0xF0, ROM_address); 00107 } 00108 00109 bool MAX31850::unassignedProbe(DigitalInOut *pin, char *ROM_address) { 00110 return search_ROM_routine(pin, 0xF0, ROM_address); 00111 } 00112 00113 bool MAX31850::search_ROM_routine(DigitalInOut *pin, char command, char *ROM_address) { 00114 bool DS1820_done_flag = false; 00115 int DS1820_last_discrepancy = 0; 00116 char DS1820_search_ROM[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 00117 00118 int discrepancy_marker, ROM_bit_index; 00119 bool return_value, Bit_A, Bit_B; 00120 char byte_counter, bit_mask; 00121 00122 return_value=false; 00123 while (!DS1820_done_flag) { 00124 if (!onewire_reset(pin)) { 00125 return false; 00126 } else { 00127 ROM_bit_index=1; 00128 discrepancy_marker=0; 00129 char command_shift = command; 00130 for (int n=0; n<8; n++) { // Search ROM command 00131 onewire_bit_out(pin, command_shift & 0x01); 00132 command_shift = command_shift >> 1; // now the next bit is in the least sig bit position. 00133 } 00134 byte_counter = 0; 00135 bit_mask = 0x01; 00136 while (ROM_bit_index<=64) { 00137 Bit_A = onewire_bit_in(pin); 00138 Bit_B = onewire_bit_in(pin); 00139 if (Bit_A & Bit_B) { 00140 discrepancy_marker = 0; // data read error, this should never happen 00141 ROM_bit_index = 0xFF; 00142 } else { 00143 if (Bit_A | Bit_B) { 00144 // Set ROM bit to Bit_A 00145 if (Bit_A) { 00146 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] | bit_mask; // Set ROM bit to one 00147 } else { 00148 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] & ~bit_mask; // Set ROM bit to zero 00149 } 00150 } else { 00151 // both bits A and B are low, so there are two or more devices present 00152 if ( ROM_bit_index == DS1820_last_discrepancy ) { 00153 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] | bit_mask; // Set ROM bit to one 00154 } else { 00155 if ( ROM_bit_index > DS1820_last_discrepancy ) { 00156 DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] & ~bit_mask; // Set ROM bit to zero 00157 discrepancy_marker = ROM_bit_index; 00158 } else { 00159 if (( DS1820_search_ROM[byte_counter] & bit_mask) == 0x00 ) 00160 discrepancy_marker = ROM_bit_index; 00161 } 00162 } 00163 } 00164 onewire_bit_out (pin, DS1820_search_ROM[byte_counter] & bit_mask); 00165 ROM_bit_index++; 00166 if (bit_mask & 0x80) { 00167 byte_counter++; 00168 bit_mask = 0x01; 00169 } else { 00170 bit_mask = bit_mask << 1; 00171 } 00172 } 00173 } 00174 DS1820_last_discrepancy = discrepancy_marker; 00175 if (ROM_bit_index != 0xFF) { 00176 int i = 1; 00177 node *list_container; 00178 while(1) { 00179 list_container = probes.pop(i); 00180 if (list_container == NULL) { //End of list, or empty list 00181 if (ROM_checksum_error(DS1820_search_ROM)) { // Check the CRC 00182 return false; 00183 } 00184 for(byte_counter=0;byte_counter<8;byte_counter++) 00185 ROM_address[byte_counter] = DS1820_search_ROM[byte_counter]; 00186 return true; 00187 } else { //Otherwise, check if ROM is already known 00188 bool equal = true; 00189 MAX31850 00190 *pointer = (MAX31850 00191 *) list_container->data ; 00192 char *ROM_compare = pointer->_ROM; 00193 00194 for(byte_counter=0;byte_counter<8;byte_counter++) { 00195 if ( ROM_compare[byte_counter] != DS1820_search_ROM[byte_counter]) 00196 equal = false; 00197 } 00198 if (equal) 00199 break; 00200 else 00201 i++; 00202 } 00203 } 00204 } 00205 } 00206 if (DS1820_last_discrepancy == 0) 00207 DS1820_done_flag = true; 00208 } 00209 return return_value; 00210 } 00211 00212 void MAX31850::match_ROM() { 00213 // Used to select a specific device 00214 int i; 00215 onewire_reset(&this->_datapin); 00216 onewire_byte_out( 0x55); //Match ROM command 00217 for (i=0;i<8;i++) { 00218 onewire_byte_out(_ROM[i]); 00219 } 00220 } 00221 00222 void MAX31850::skip_ROM() { 00223 onewire_reset(&this->_datapin); 00224 onewire_byte_out(0xCC); // Skip ROM command 00225 } 00226 00227 bool MAX31850::ROM_checksum_error(char *_ROM_address) { 00228 char _CRC=0x00; 00229 int i; 00230 for(i=0;i<7;i++) // Only going to shift the lower 7 bytes 00231 _CRC = CRC_byte(_CRC, _ROM_address[i]); 00232 // After 7 bytes CRC should equal the 8th byte (ROM CRC) 00233 return (_CRC!=_ROM_address[7]); // will return true if there is a CRC checksum mis-match 00234 } 00235 00236 bool MAX31850::scratchpad_checksum_error() { 00237 char _CRC=0x00; 00238 int i; 00239 for(i=0;i<8;i++) // Only going to shift the lower 8 bytes 00240 _CRC = CRC_byte(_CRC, scratchpad[i]); 00241 // After 8 bytes CRC should equal the 9th byte (scratchpad CRC) 00242 return (_CRC!=scratchpad[8]); // will return true if there is a CRC checksum mis-match 00243 } 00244 00245 char MAX31850::CRC_byte (char _CRC, char byte ) { 00246 int j; 00247 for(j=0;j<8;j++) { 00248 if ((byte & 0x01 ) ^ (_CRC & 0x01)) { 00249 // DATA ^ LSB CRC = 1 00250 _CRC = _CRC>>1; 00251 // Set the MSB to 1 00252 _CRC = _CRC | 0x80; 00253 // Check bit 3 00254 if (_CRC & 0x04) { 00255 _CRC = _CRC & 0xFB; // Bit 3 is set, so clear it 00256 } else { 00257 _CRC = _CRC | 0x04; // Bit 3 is clear, so set it 00258 } 00259 // Check bit 4 00260 if (_CRC & 0x08) { 00261 _CRC = _CRC & 0xF7; // Bit 4 is set, so clear it 00262 } else { 00263 _CRC = _CRC | 0x08; // Bit 4 is clear, so set it 00264 } 00265 } else { 00266 // DATA ^ LSB CRC = 0 00267 _CRC = _CRC>>1; 00268 // clear MSB 00269 _CRC = _CRC & 0x7F; 00270 // No need to check bits, with DATA ^ LSB CRC = 0, they will remain unchanged 00271 } 00272 byte = byte>>1; 00273 } 00274 return _CRC; 00275 } 00276 00277 void MAX31850::readAll() { 00278 // Convert temperature into scratchpad for all devices at once 00279 int delay_time = 75; //default delay time 00280 00281 skip_ROM(); //Skip ROM command, will convert for all devices 00282 00283 onewire_byte_out( 0x44); //perform temperature conversion 00284 00285 wait_ms(delay_time); 00286 } 00287 00288 void MAX31850::read_scratchpad() { 00289 // This will copy the MAX31850's 9 bytes of scratchpad data 00290 // into the objects scratchpad array. Functions that use 00291 // scratchpad values will automaticaly call this procedure. 00292 int i; 00293 match_ROM(); // Select this device 00294 onewire_byte_out( 0xBE); //Read Scratchpad command 00295 for(i=0;i<9;i++) { 00296 scratchpad[i] = onewire_byte_in(); 00297 } 00298 } 00299 00300 00301 float MAX31850::getTemp(int scale) { 00302 float answer; 00303 int reading; 00304 read_scratchpad(); 00305 if (scratchpad_checksum_error()) { 00306 //indicate we got a CRC error 00307 answer = invalid_conversion; 00308 pc.printf("CRC Error\r\n"); 00309 } 00310 else { 00311 reading = (scratchpad[1] << 8) + scratchpad[0]; //combine first two bytes of scratchpad 00312 reading = reading >> 2; //shift right two to drop unused bits 00313 if (reading & 0x2000) { //check MSB to determin sign 00314 reading = 0-((reading ^ 0x3fff) + 1); //use 2's compliment to convert back to positive number and make it a signed int 00315 } 00316 answer = reading +0.0; //convert to floating point 00317 answer = answer / 4.0; //shift decimal place over two places 00318 00319 //unit convertion 00320 //checks for passed in value first and if there is none it sets the units baced on class units variable 00321 switch(scale) { 00322 case C: 00323 break; 00324 case K: 00325 answer = answer + 273.15f; 00326 break; 00327 case F: 00328 answer = answer * 1.8f + 32.0f; 00329 break; 00330 case R: 00331 answer = answer * 1.8f + 491.67f; 00332 break; 00333 default: 00334 switch(_units) { 00335 case C: 00336 break; 00337 case K: 00338 answer = answer + 273.15f; 00339 break; 00340 case F: 00341 answer = answer * 1.8f + 32.0f; 00342 break; 00343 case R: 00344 answer = answer * 1.8f + 491.67f; 00345 break; 00346 } 00347 } 00348 } 00349 return answer; 00350 } 00351 00352 // Contributed by John M. Larkin (jlarkin@whitworth.edu) 00353 unsigned long long MAX31850::getId() { 00354 // This will return the 64 bit address of the connected MAX31850 00355 unsigned long long myName = 0; 00356 for (int i = 0; i<8; i++) { 00357 myName = (myName<<8) | _ROM[i]; 00358 } 00359 return myName; 00360 } 00361 00362 void MAX31850::setUnits(int units) { 00363 _units = units; 00364 }
Generated on Wed Jul 13 2022 22:04:08 by 1.7.2