Определяем температуру… без внешних датчиков

Бывает полезно знать температуру окружающей изделие среды. В этом, как ни странно, может помочь… сам микроконтроллер, встроенный в конструкцию.

Современные микроконтроллеры AVR в своем кристалле, кроме всевозможной аналоговой и цифровой «периферии», имеют еще и термодатчик.

Считывание информации с встроенного датчика производится обычной процедурой аналого-цифрового преобразования, т.е. в Arduino — функцией analogRead(). Остается выяснить: к какому  входу мультиплексора подключен датчик. Об этом можно узнать из описания микросхемы, например для ATmega48/88/168 — это (смотрим раздел ADC — Analog to Digital Converter):avr_mux

Описанию работы с датчиком температуры посвящен целый раздел описания —  Temperature Measurement. Кроме выбора канала мультиплексора, требуется установить источник опорного напряжения для АЦП : 1,1В (The internal 1.1V voltage reference must also be selected for the ADC voltage reference source in the temperature sensor measurement).

Atmel постаралась «соорудить» вполне адекватный датчик, однако, ожидать от него каких-то «сверх» параметров — довольно «смело»! Нам обещают вполне линейную характеристику и «чувствительность» примерно 1мВ/Градус, однако точность измерения — «совсем никакая» = 10 градусов. Ну, что есть — то есть…

Для получения реального значения температуры, производитель рекомендует производить калибровку датчика, а потом в приложениях использовать формулу:

 T = { [(ADCH << 8) | ADCL] — TOS} / k

здесь: ADCL и ADCH — младший и старший байты регистра ADC АЦП, а вот TOS и k — надо будет экспериментально определять для каждой микросхемы и где-нибудь (например в EEPROM) хранить.

Пример использования датчика я обнаружил на сайте Digistump. Для ATtiny85 (Digispark) скетч привожу ниже:

/*  Измеренное значение температуры (внутренний датчик ATtiny85)  индицируется числом вспышек с последующей паузой 2 сек    
modified 27 august 2016  by Apakhom */
int get_temp() {
  // см  http://digistump.com/wiki/digispark/quickref
  analogReference(INTERNAL1V1);
  int raw = analogRead(A0+15); 
  /* Original code used a 13 deg adjustment. But based on my results, I didn't seem to need it. */
  // raw -= 13; // raw adjust = kelvin //this value is used to calibrate to your chip
  int in_c = raw - 273; // celcius
  analogReference(DEFAULT);
  return in_c;
}

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 1 as an output.
  pinMode(1, OUTPUT);  //Digispark type A  (LED on pin1)
}

void blink_one_time()  {
  digitalWrite(1, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(300);              // wait for a second
  digitalWrite(1, LOW);    // turn the LED off by making the voltage LOW
  delay(300);              // wait for a second
}

// the loop function runs over and over again forever
void loop() {
  int m = get_temp();
  for (int i=1; i<=m; i++) { 
     blink_one_time();
  }
  delay(2000);
}

Как видно, главная «фишка» скетча в функции get_temp() — тут она используется без изменений — как в первоисточнике:

  • В ATtiny85 датчик температуры подключен к аналоговому мультиплексору по адресу  MUX[3:0] bits in ADMUX register to “1111”, поэтому аргументом в функции analogRead() указано A0+15.
  • Перед считыванием температуры включается источник опорного напряжения для АЦП = 1,1В; после измерения — он сбрасывается в «дефолт».
  • Про калибровку (-13 градусов) — не зря в комментариях написано… На практике, я получил 42 градуса на модуле Digispark в разъеме USB компьютера на сильно нагретой стенке; тоже на удлинителе при комнатной температуре дало 38 градусов, так что вычесть 13 градусов — будет совсем не лишним.

В приведенном примере индикация выполнена на том что есть в Digispark — контрольный светодиод мигает столько раз, сколько градусов измерено…

Добавить комментарий

Ваш e-mail не будет опубликован.

Нажимая кнопку "Отправить" Вы даёте свое согласие на обработку введенной персональной информации в соответствии с Федеральным Законом №152-ФЗ от 27.07.2006 "О персональных данных".