Library for MAX31850 thermocouple temperature sensor
MAX31850.cpp
- Committer:
- croberts21
- Date:
- 2019-01-23
- Revision:
- 0:5530bf2d0e94
File content as of revision 0:5530bf2d0e94:
#include "MAX31850.h" Serial pc(USBTX, USBRX); #define ONEWIRE_INPUT(pin) pin->input() #define ONEWIRE_OUTPUT(pin) pin->output() #define ONEWIRE_INIT(pin) LinkedList<node> MAX31850::probes; MAX31850::MAX31850 (PinName data_pin, PinName power_pin, bool power_polarity) : _datapin(data_pin), _parasitepin(power_pin) { int byte_counter; _power_polarity = power_polarity; _power_mosfet = power_pin != NC; for(byte_counter=0;byte_counter<9;byte_counter++) scratchpad[byte_counter] = 0x00; ONEWIRE_INIT((&_datapin)); if (!unassignedProbe(&_datapin, _ROM)) error("No unassigned MAX31850 found!\n"); else { _datapin.input(); probes.append(this); _parasite_power = false; //only set up to use external power right now } } MAX31850::~MAX31850 (void) { node *tmp; for(int i=1; i<=probes.length(); i++) { tmp = probes.pop(i); if (tmp->data == this) probes.remove(i); } } bool MAX31850::onewire_reset(DigitalInOut *pin) { // This will return false if no devices are present on the data bus bool presence=false; ONEWIRE_OUTPUT(pin); pin->write(0); // bring low for 500 us wait_us(500); ONEWIRE_INPUT(pin); // let the data line float high wait_us(90); // wait 90us if (pin->read()==0) // see if any devices are pulling the data line low presence=true; wait_us(410); return presence; } void MAX31850::onewire_bit_out (DigitalInOut *pin, bool bit_data) { ONEWIRE_OUTPUT(pin); pin->write(0); wait_us(3); // DXP modified from 5 if (bit_data) { pin->write(1); // bring data line high wait_us(55); } else { wait_us(55); // keep data line low pin->write(1); wait_us(10); // DXP added to allow bus to float high before next bit_out } } void MAX31850::onewire_byte_out(char data) { // output data character (least sig bit first). int n; for (n=0; n<8; n++) { onewire_bit_out(&this->_datapin, data & 0x01); data = data >> 1; // now the next bit is in the least sig bit position. } } bool MAX31850::onewire_bit_in(DigitalInOut *pin) { bool answer; ONEWIRE_OUTPUT(pin); pin->write(0); wait_us(3); // DXP modified from 5 ONEWIRE_INPUT(pin); wait_us(10); // DXP modified from 5 answer = pin->read(); wait_us(45); // DXP modified from 50 return answer; } char MAX31850::onewire_byte_in() { // read byte, least sig byte first char answer = 0x00; int i; for (i=0; i<8; i++) { answer = answer >> 1; // shift over to make room for the next bit if (onewire_bit_in(&this->_datapin)) answer = answer | 0x80; // if the data port is high, make this bit a 1 } return answer; } bool MAX31850::unassignedProbe(PinName pin) { DigitalInOut _pin(pin); ONEWIRE_INIT((&_pin)); char ROM_address[8]; return search_ROM_routine(&_pin, 0xF0, ROM_address); } bool MAX31850::unassignedProbe(DigitalInOut *pin, char *ROM_address) { return search_ROM_routine(pin, 0xF0, ROM_address); } bool MAX31850::search_ROM_routine(DigitalInOut *pin, char command, char *ROM_address) { bool DS1820_done_flag = false; int DS1820_last_discrepancy = 0; char DS1820_search_ROM[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int discrepancy_marker, ROM_bit_index; bool return_value, Bit_A, Bit_B; char byte_counter, bit_mask; return_value=false; while (!DS1820_done_flag) { if (!onewire_reset(pin)) { return false; } else { ROM_bit_index=1; discrepancy_marker=0; char command_shift = command; for (int n=0; n<8; n++) { // Search ROM command onewire_bit_out(pin, command_shift & 0x01); command_shift = command_shift >> 1; // now the next bit is in the least sig bit position. } byte_counter = 0; bit_mask = 0x01; while (ROM_bit_index<=64) { Bit_A = onewire_bit_in(pin); Bit_B = onewire_bit_in(pin); if (Bit_A & Bit_B) { discrepancy_marker = 0; // data read error, this should never happen ROM_bit_index = 0xFF; } else { if (Bit_A | Bit_B) { // Set ROM bit to Bit_A if (Bit_A) { DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] | bit_mask; // Set ROM bit to one } else { DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] & ~bit_mask; // Set ROM bit to zero } } else { // both bits A and B are low, so there are two or more devices present if ( ROM_bit_index == DS1820_last_discrepancy ) { DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] | bit_mask; // Set ROM bit to one } else { if ( ROM_bit_index > DS1820_last_discrepancy ) { DS1820_search_ROM[byte_counter] = DS1820_search_ROM[byte_counter] & ~bit_mask; // Set ROM bit to zero discrepancy_marker = ROM_bit_index; } else { if (( DS1820_search_ROM[byte_counter] & bit_mask) == 0x00 ) discrepancy_marker = ROM_bit_index; } } } onewire_bit_out (pin, DS1820_search_ROM[byte_counter] & bit_mask); ROM_bit_index++; if (bit_mask & 0x80) { byte_counter++; bit_mask = 0x01; } else { bit_mask = bit_mask << 1; } } } DS1820_last_discrepancy = discrepancy_marker; if (ROM_bit_index != 0xFF) { int i = 1; node *list_container; while(1) { list_container = probes.pop(i); if (list_container == NULL) { //End of list, or empty list if (ROM_checksum_error(DS1820_search_ROM)) { // Check the CRC return false; } for(byte_counter=0;byte_counter<8;byte_counter++) ROM_address[byte_counter] = DS1820_search_ROM[byte_counter]; return true; } else { //Otherwise, check if ROM is already known bool equal = true; MAX31850 *pointer = (MAX31850 *) list_container->data; char *ROM_compare = pointer->_ROM; for(byte_counter=0;byte_counter<8;byte_counter++) { if ( ROM_compare[byte_counter] != DS1820_search_ROM[byte_counter]) equal = false; } if (equal) break; else i++; } } } } if (DS1820_last_discrepancy == 0) DS1820_done_flag = true; } return return_value; } void MAX31850::match_ROM() { // Used to select a specific device int i; onewire_reset(&this->_datapin); onewire_byte_out( 0x55); //Match ROM command for (i=0;i<8;i++) { onewire_byte_out(_ROM[i]); } } void MAX31850::skip_ROM() { onewire_reset(&this->_datapin); onewire_byte_out(0xCC); // Skip ROM command } bool MAX31850::ROM_checksum_error(char *_ROM_address) { char _CRC=0x00; int i; for(i=0;i<7;i++) // Only going to shift the lower 7 bytes _CRC = CRC_byte(_CRC, _ROM_address[i]); // After 7 bytes CRC should equal the 8th byte (ROM CRC) return (_CRC!=_ROM_address[7]); // will return true if there is a CRC checksum mis-match } bool MAX31850::scratchpad_checksum_error() { char _CRC=0x00; int i; for(i=0;i<8;i++) // Only going to shift the lower 8 bytes _CRC = CRC_byte(_CRC, scratchpad[i]); // After 8 bytes CRC should equal the 9th byte (scratchpad CRC) return (_CRC!=scratchpad[8]); // will return true if there is a CRC checksum mis-match } char MAX31850::CRC_byte (char _CRC, char byte ) { int j; for(j=0;j<8;j++) { if ((byte & 0x01 ) ^ (_CRC & 0x01)) { // DATA ^ LSB CRC = 1 _CRC = _CRC>>1; // Set the MSB to 1 _CRC = _CRC | 0x80; // Check bit 3 if (_CRC & 0x04) { _CRC = _CRC & 0xFB; // Bit 3 is set, so clear it } else { _CRC = _CRC | 0x04; // Bit 3 is clear, so set it } // Check bit 4 if (_CRC & 0x08) { _CRC = _CRC & 0xF7; // Bit 4 is set, so clear it } else { _CRC = _CRC | 0x08; // Bit 4 is clear, so set it } } else { // DATA ^ LSB CRC = 0 _CRC = _CRC>>1; // clear MSB _CRC = _CRC & 0x7F; // No need to check bits, with DATA ^ LSB CRC = 0, they will remain unchanged } byte = byte>>1; } return _CRC; } void MAX31850::readAll() { // Convert temperature into scratchpad for all devices at once int delay_time = 75; //default delay time skip_ROM(); //Skip ROM command, will convert for all devices onewire_byte_out( 0x44); //perform temperature conversion wait_ms(delay_time); } void MAX31850::read_scratchpad() { // This will copy the MAX31850's 9 bytes of scratchpad data // into the objects scratchpad array. Functions that use // scratchpad values will automaticaly call this procedure. int i; match_ROM(); // Select this device onewire_byte_out( 0xBE); //Read Scratchpad command for(i=0;i<9;i++) { scratchpad[i] = onewire_byte_in(); } } float MAX31850::getTemp(int scale) { float answer; int reading; read_scratchpad(); if (scratchpad_checksum_error()) { //indicate we got a CRC error answer = invalid_conversion; pc.printf("CRC Error\r\n"); } else { reading = (scratchpad[1] << 8) + scratchpad[0]; //combine first two bytes of scratchpad reading = reading >> 2; //shift right two to drop unused bits if (reading & 0x2000) { //check MSB to determin sign reading = 0-((reading ^ 0x3fff) + 1); //use 2's compliment to convert back to positive number and make it a signed int } answer = reading +0.0; //convert to floating point answer = answer / 4.0; //shift decimal place over two places //unit convertion //checks for passed in value first and if there is none it sets the units baced on class units variable switch(scale) { case C: break; case K: answer = answer + 273.15f; break; case F: answer = answer * 1.8f + 32.0f; break; case R: answer = answer * 1.8f + 491.67f; break; default: switch(_units) { case C: break; case K: answer = answer + 273.15f; break; case F: answer = answer * 1.8f + 32.0f; break; case R: answer = answer * 1.8f + 491.67f; break; } } } return answer; } // Contributed by John M. Larkin (jlarkin@whitworth.edu) unsigned long long MAX31850::getId() { // This will return the 64 bit address of the connected MAX31850 unsigned long long myName = 0; for (int i = 0; i<8; i++) { myName = (myName<<8) | _ROM[i]; } return myName; } void MAX31850::setUnits(int units) { _units = units; }