Логические уровни и подтяжки
Почему Arduino и Raspberry Pi иногда не дружат? 🤔 Почему кнопка без резистора «глючит»? И как не сжечь вход микроконтроллера?
Всё дело в логических уровнях.
🎓 В курсе nand2cpuВсе наши схемы работают на 5 В — это классические TTL-уровни: Урок 1: Вентиль NAND
Что такое 0 и 1 на самом деле
Цифровая электроника не видит «0» и «1» — она видит напряжение:
5В ─────┬───────────────────── VCC
│
│ ████████ ← Это "1" (HIGH)
│ ████████
~2.5В ─┼───────────── граница (не точная!)
│
│ ████████ ← Это "0" (LOW)
│ ████████
0В ─────┴───────────────────── GND
Но граница — не ровно посередине! У разных микросхем разные пороги.
5 В vs 3.3 В — главная проблема
5V логика 3.3V логика
5.0 В ─── HIGH ─── 💥 ОПАСНО!
3.3 В ─── HIGH ─── HIGH (VCC)
2.0 В ─── ? ─── ?
0.8 В ─── LOW ─── LOW
0 В ─── LOW ─── LOW
Arduino (5 В) → Raspberry Pi (3.3 В)
Arduino Raspberry Pi
5 В ───────────► 3.3 В вход
⚠️ ПЛОХО! Может сжечь вход Pi!
Raspberry Pi (3.3 В) → Arduino (5 В)
Raspberry Pi Arduino
3.3 В ─────────► 5 В вход
✅ Обычно OK — Arduino видит 3.3 В как "1"
(но проверь datasheet!)
Как подружить 5 В и 3.3 В
Способ 1: Делитель напряжения (самый простой)
Два резистора делят напряжение:
5 В ────[10k]────┬────► ~3.3 В
│
[20k]
│
GND ─────────────┘
Формула: $U_{out} = U_{in} \times \frac{R_2}{R_1 + R_2} = 5 \times \frac{20}{30} ≈ 3.3$ В
Популярные комбинации:
| R1 | R2 | Результат |
|---|---|---|
| 10 кОм | 20 кОм | 3.33 В |
| 1 кОм | 2 кОм | 3.33 В |
| 10 кОм | 22 кОм | 3.44 В |
✅ Плюс: очень просто, 2 детали
❌ Минус: только для медленных сигналов (кнопки, датчики)
Способ 2: Модуль level shifter
Для быстрых сигналов (I²C, SPI, UART) используй готовый модуль:
┌─────────────────────┐
│ Level Shifter │
│ │
│ HV ──── 5 В │ HV = High Voltage
│ LV ──── 3.3 В │ LV = Low Voltage
│ │
│ HV1 ◄───► LV1 │ ← двунаправленный!
│ HV2 ◄───► LV2 │
│ HV3 ◄───► LV3 │
│ HV4 ◄───► LV4 │
└─────────────────────┘
Ищи на AliExpress: «logic level converter» или «level shifter 3.3v 5v»
Типы входов и выходов
Вход (INPUT)
┌───────┐
Сигнал ─────────┤ ВХОД │
│ │ "Слушает" напряжение
└───────┘
Вход имеет очень большое сопротивление — почти не потребляет ток.
Выход Push-Pull (обычный)
VCC
│
[T1] ← включается для "1"
│
OUT ─────┼──► активно выдаёт 0 или 1
│
[T2] ← включается для "0"
│
GND
Может толкать ток наружу (1) и тянуть ток внутрь (0).
Выход Open-Drain (открытый сток)
VCC
│
[pull-up] ← внешний резистор!
│
OUT ─────┼──►
│
[T] ← только тянет вниз
│
GND
Может только притягивать к GND. Для «1» нужна внешняя подтяжка.
Где используется: I²C (SDA, SCL), кнопки, много устройств на одной линии.
Подтяжка — зачем она нужна
Проблема: вход без подключения «висит в воздухе» и ловит помехи.
НЕПРАВИЛЬНО: ПРАВИЛЬНО:
Кнопка VCC
│ │
│ [10k] ← pull-up
│ │
МК ────┴── ? МК ┼──── = 1 (покой)
│
"Плавает" Кнопка
случайные 0/1 │
GND ── = 0 (нажата)
Pull-up (к питанию)
VCC ────[R]────┬──── МК вход
│
Кнопка
│
GND ───────────┘
Покой: вход = 1
Нажата: вход = 0
Pull-down (к земле)
VCC ───────────┐
│
Кнопка
│
МК вход ──┬────┘
│
GND ────[R]
Покой: вход = 0
Нажата: вход = 1
Типичные номиналы подтяжки
| Применение | Резистор | Почему |
|---|---|---|
| Кнопка | 10 кОм | Стандарт, низкий ток |
| I²C | 4.7 кОм | Быстрее, стандарт |
| Длинные провода | 2.2–4.7 кОм | Сильнее, против помех |
| Экономия батареи | 47–100 кОм | Минимальный ток |
Встроенные подтяжки
У большинства микроконтроллеров есть внутренние pull-up:
// Arduino
pinMode(2, INPUT_PULLUP);
// STM32 / ESP32
gpio_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_ONLY);
✅ Удобно — не нужен внешний резистор
❌ Слабые (20–50 кОм) — для длинных проводов лучше внешний
Практическая шпаргалка
Кнопка — как подключить
Вариант 1 (pull-up): Вариант 2 (внутренний):
VCC VCC
│ │
[10k] [внутр.]
│ │
├───► МК ├───► МК (INPUT_PULLUP)
│ │
[BTN] [BTN]
│ │
GND GND
Нажата = 0 Нажата = 0
Отпущена = 1 Отпущена = 1
Датчик (5 В) → МК (3.3 В)
Датчик МК 3.3В
│ │
├──[10k]──┬──[20k]──GND │
│ │ │
└─────────┴────────────────┘
~3.3 В
I²C — два устройства с разным питанием
3.3V ──────┬──────────┬───── LV (level shifter)
│ │
[4.7k] [4.7k]
│ │
SDA ─────┼──────────┼───── LV1 ◄──► HV1 ───┬─── SDA (5V устройство)
│ │ │
SCL ─────┼──────────┴───── LV2 ◄──► HV2 ───┼─── SCL
│ │
5V ────────┴──────────────────────────── HV ─┘
Опасные ошибки
| Ошибка | Последствие | Как избежать |
|---|---|---|
| 5 В → 3.3 В вход | 💥 Сгоревший пин | Делитель или level shifter |
| Вход «в воздухе» | Случайные 0/1 | Всегда подтяжка! |
| Слишком слабый pull-up для I²C | Не работает | Используй 4.7 кОм |
| Забыл общий GND | Ничего не работает | Соедини GND всех устройств |
Связь с другими темами
- Антидребезг — кнопки и подтяжки: debouncing
- Логические элементы — TTL/CMOS уровни: logic_gates
- Резисторы — делители напряжения: резисторы
- nand2cpu — работаем на 5 В: Акт I
Мини-задания
Arduino выдаёт 5 В, а ESP32 принимает 3.3 В. Какие резисторы взять для делителя?
Почему кнопка без подтяжки иногда «нажимается сама»?
Какой резистор pull-up взять для I²C?
В чём разница между push-pull и open-drain выходом?
Можно ли подать 3.3 В сигнал на 5 В вход Arduino?
Details
R1 = 10 кОм, R2 = 20 кОм (или 1 кОм и 2 кОм) — получится ~3.3 В
Вход «плавает» и ловит электромагнитные помехи — показывает случайные значения
4.7 кОм — стандарт для I²C
Push-pull активно выдаёт и 0, и 1. Open-drain только притягивает к 0, для 1 нужна внешняя подтяжка
Обычно да — Arduino видит 3.3 В как логическую «1» (порог ~2 В), но лучше проверить datasheet
