Library for MAX31850 thermocouple temperature sensor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX31850.cpp Source File

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 }