LM35 і TMP36: аналоговий термометр на ESP32 та Arduino без бібліотек
Три ніжки, 10 мВ на градус і жодної бібліотеки. Розбираємося, чим LM35 відрізняється від TMP36, чому на ESP32 варто читати мілівольти, а не «сирі» значення АЦП, і як усередненням прибрати стрибки показів.
Про проєкт
LM35 і TMP36 — найпростіші датчики температури: мікросхема в корпусі TO-92, як у транзистора, видає напругу, пропорційну температурі. Жодної шини, адрес і бібліотек — лише analogRead(). Саме тому на них зручно розібратися з АЦП мікроконтролера і його похибками.
Що потрібно
- ESP32 DevKit (або Arduino Uno / Nano)
- Датчик LM35DZ або TMP36
- Кілька проводів; для довгого кабелю — конденсатор 0.1 мкФ між OUT і GND
LM35 чи TMP36
| LM35 | TMP36 | |
|---|---|---|
| Крутизна | 10 мВ/°C | 10 мВ/°C |
| 0 °C | 0 мВ | 500 мВ |
| Живлення | 4–30 В | 2.7–5.5 В |
| Діапазон з одним живленням | +2…+150 °C | −40…+125 °C |
| Формула | T = U / 10 | T = (U − 500) / 10 |
Головна пастка LM35 — живлення від 4 В. Від 3.3 В він формально не працює, тому на ESP32 його підключають до виводу 5V: вихідна напруга однаково не перевищить 1.5 В, і для входу ESP32 це безпечно. Друга особливість — з одним живленням LM35 не видає від'ємної напруги, тож мінус на ньому не побачити. Для вулиці беріть TMP36 або DS18B20.
Схема
Якщо тримати датчик плоским боком до себе, ніжки зліва направо: +Vs, Vout, GND.
| Датчик | ESP32 | Arduino Uno |
|---|---|---|
| +Vs | 5V (LM35) або 3V3 (TMP36) | 5V |
| Vout | GPIO34 (ADC1) | A0 |
| GND | GND | GND |
На ESP32 використовуйте виводи ADC1 (GPIO32–39): ADC2 не працює, коли ввімкнено Wi-Fi.
Чому мілівольти, а не analogRead()
АЦП ESP32 нелінійний: біля нуля і біля верхньої межі він «з'їдає» десятки мілівольт, а коефіцієнт відрізняється від чипа до чипа. analogRead() * 3.3 / 4095 легко дає похибку 2–3 °C. Функція analogReadMilliVolts() застосовує заводську калібровку, записану в eFuse, і повертає напругу в мілівольтах — для LM35 це одразу десяті частки градуса.
На Arduino Uno АЦП лінійний, але грубий: 10 біт від 5 В — це 4.9 мВ на крок, тобто приблизно 0.5 °C. Точніше можна, якщо перемкнути опорну напругу на внутрішні 1.1 В (analogReference(INTERNAL)): тоді крок — 0.1 °C, а максимум — 110 °C.
Код
// LM35 / TMP36 на ESP32: усереднюємо виміри і переводимо мілівольти в °C
const int SENSOR_PIN = 34; // ADC1
const bool IS_TMP36 = false; // true для TMP36 (0 °C = 500 мВ)
float readCelsius() {
uint32_t sum = 0;
for (int i = 0; i < 16; i++) {
sum += analogReadMilliVolts(SENSOR_PIN); // мілівольти з заводською калібровкою
delay(2);
}
float mv = sum / 16.0;
return IS_TMP36 ? (mv - 500) / 10.0 : mv / 10.0;
}
void setup() {
Serial.begin(115200);
}
void loop() {
float t = readCelsius();
Serial.printf("Температура: %.1f °C\n", t);
delay(1000);
}
Шістнадцять вимірів із паузою 2 мс усереднюють шум АЦП і наведення від Wi-Fi. У симуляторі змінюйте температуру у властивостях датчика і перемикайте модель на TMP36 — не забудьте тоді виправити IS_TMP36.
Типові проблеми
- Показує на 5–10 °C більше, ніж є. Датчик гріється сам від себе або від плати. Винесіть його на проводі подалі від стабілізатора.
- Покази стрибають на довгому кабелі. LM35 не любить ємності кабелю: поставте резистор 2 кОм послідовно з виходом або конденсатор 0.1 мкФ на GND біля входу АЦП.
- Живлення 3.3 В. LM35 від 3.3 В бреше або «застигає» — симулятор про це попередить.
- Крок 0.5 °C на Arduino. Це обмеження 10-бітного АЦП; допоможе
analogReference(INTERNAL)або цифровий датчик.