How to read an SMT 160-30 ?


The SMT160-30 ist outdated. Better go for the SMT172 which offers better data but still is pin- and function-compatible.

The SMARTEC SMT-160-30 is not the cheapest temperature sensor but it is very accurate. The datasheet tells you that the data are given as a PWM output and the PWM duty cycle lets you calculate the temperature by this formula:

D.C. = 0.320 + 0.00470 * t

so to get the temperature you have to calculate

t = (D.C. - 0.32) / 0.0047

To read the duty cycle you have to use a timer. Most of the timers have only an 8 bit or 16 bit resolution, so this is the limit for the accuracy you get.

If you want better results it can be done by reading the PWM signal again and again and calculation the ratio of HIGH readings. Chiara Taddia proposed a random sampling technique running over any peroid of time to get better results.

Further more you might want to get rid of the floating point calculations. This can be done by multiplying the numerator and denominator by adequate numbers.

For some reason we used pin A0 as data input which can be read by PINC & 1. If you prefer to use another pin make sure you use the proper PORT and bit mask. If you do not use bit d0 you have to shift the counter c accordingly before calculating the duty cycle.

This sketch shows how it can be done:

/*  SMT 160-30, random sampling technique, Taddia Chiara, 2007
 *  duty cycle dc = 0.320 + 0.0047 * t = c / samples 
 *  remove floating point arithmetic:
 *  temperature t = (dc - 0.32) / 0.0047 = (dc * 100 - 32) / 0.47
 *       = (c / samples - 0.32) / 0.0047
 *       = (c - 32 * samples / 100) / (samples * 0.0047)
 *  Choose samples = 600*35461 = 21.276.600, so samples * 0.0047 = 100.000,02
 *  By rounding to 10.000, only integers remain: 
 *  t = (c - 32 * samples / 100) / 100.000
 *  Input Pin = A0 (PORT C, digitalRead)
 */

const long i1 = 600;
const word k1 = 35461;
const long samples = i1 * k1;
const long r = samples * 0.0047;
  
void setup() {
  Serial.begin(9600);
  Serial.println(F(__FILE__));
  Serial.print(F(__TIME__));
  Serial.print(F(", "));
  Serial.println(F(__DATE__));
  Serial.print(F("samples: "));
  Serial.println(samples);
  Serial.print(F("r: "));
  Serial.println(r);
  delay(70);
}

void loop() {
  long c = 0; // counts the HIGH values
  cli();  
  for (long i = 0; i < i1; i++) {
    word j = 0; // j must not overflow
    for (word k = 0; k < k1; k++) 
      j = j + (PINC & 1);
    c = c + j;
  }
  sei();
  long t = c - 32 * samples / 100;
  byte b = t / r;
  long q = t % r;
  Serial.print(b);
  Serial.print(F(","));  // replace the decimal separator by a dot if needed 
  String s = String(q);  // in case the fractional part starts with zero
  while (s.length() < 5) s = "0"+s;
  Serial.println(s);
  delay(20);
}

And this is how the results look like: and when exported to EXCEL
21,49924
21,47477
21,47249
21,45527
21,41755
21,39921
21,39291
21,40874
21,41405
21,41987
21,43104
21,42957
21,43991
21,44694
...
...

Actually, the resolution is much better than 0.01 °C:




contact: nji(at)gmx.de