Measuring temperatures with TMP03/04 (Part 4)

Part 12345, 6, 7, 8

Here are the lastest developments in the library (PlainTMP) which handles the TMP0x series temperature sensors from Analog Devices. The core function performs temperature measurement on TMP03, TMP04, TMP05 and TMP06 ratiometric sensors. The last two ones must be configured in continuous measurement mode (Pin 2 is left floating). The options from this function allow:

  • Sensor type selection (one of the TMP0x sensors)
  • PORTx selection
  • PINx selection
  • Unit (°K, °C or °F)
  • Averages (Oversampling 4 times is equivalent to gaining 1 precision bit)
  • Correction factors (Gain and Offset)

It includes timeout management which value can be user defined or automatically set by the function. Any error leads to an aberrant -1000 retuned value.

double PlainTMP::temperature(uint8_t type, volatile uint8_t *port, uint8_t inputPin, uint8_t unit, uint8_t averages, double corOffset, double corSlope, uint16_t timeout) {
/* 
Get the actual temperature expressed in the specified unit
corOffset and corSlope are the correction factors
timeOut is expressed in milliseconds
Function returns -1000 in case of error
*/
	uint8_t signalPinMask = (1 << inputPin);
	DDR(*port) &= ~signalPinMask; /* Make inputPin an input pin */
	if ((type == TMP_TMP03) || (type == TMP_TMP06)) {
		PORT(*port) |= signalPinMask; /* Bias inputPin */
	}
	if ((type == TMP_TMP03) || (type == TMP_TMP04)) {
		if (timeout < 112) timeout = 112; /* Twice THigh + TLow = 56 ms in the worst case */
	}
	else if ((type == TMP_TMP05) || (type == TMP_TMP06)) {
		if (timeout < 302) timeout = 302; /* Twice THigh + TLow = 151 ms in the worst case */
	}
	delay(1);
	uint32_t timeLimit = 0; /* Set timeout limit */
  uint8_t timeLimitExceeded = 0x00;
	uint32_t THigh = 0;
  uint32_t TLow = 0;
	for (uint8_t i = 0; i < averages; i++) {
		timeLimit = ((timeout * 1000UL) + micros()); /* Set timeout limit */
		while (PIN(*port) & signalPinMask) { /* Wait for low state on signal pin */
			if (micros() > timeLimit) {
				timeLimitExceeded =0x01;
				break;
			}
		}
		while (~PIN(*port) & signalPinMask) { /* Wait for high state on signal pin */ 
			if (micros() > timeLimit) {
				timeLimitExceeded =0x01;
				break;
			}
		}
		uint32_t THStart = micros();  /* THigh starts now */
		while (PIN(*port) & signalPinMask) { /* While THigh is high */ 
			if (micros() > timeLimit) {
				timeLimitExceeded =0x01;
				break;
			}
		}
		uint32_t TLStart = micros(); /* TLow starts now */
		THigh += (TLStart - THStart); /* Cumulate mesurements */
		while (~PIN(*port) & signalPinMask) { /* While TLow is low */ 
			if (micros() > timeLimit) {
				timeLimitExceeded =0x01;
				break;
			}
		}
		TLow += (micros() - TLStart); /* Cumulate mesurements */
		if (timeLimitExceeded == 0x01) {
			return(-1000.0); /* Timeout detected */
		}
	}
	double result;
	if ((type == TMP_TMP03) || (type == TMP_TMP04)) {	
		result = (235.0 - ((400.0 * THigh) / TLow));		
	}
	else if ((type == TMP_TMP05) || (type == TMP_TMP06)) {
		result = (421.0 - ((751.0 * THigh) / TLow));
	}
	if (unit == TMP_UNI_KELVIN) { 
		result = (result + 273.15); 
	}
	else if (unit == TMP_UNI_FAHRENHEIT) { 
		result = (((result * 9) / 5) + 32); 
	}
	/* Apply correction factors */
	result = (corOffset + (result * corSlope));
	return (result);
}

Nex post on same subject

Leave a Reply

You must be logged in to post a comment.