Захотелось плавно менять громкость самодельного усилителя на PAM8403: подключил потенциометр, прогнал через analogWrite — а в динамиках вместо тишины на половине оборота пищит 490-герцовый прямоугольник. Светодиод из урока про ШИМ на этой же ножке светил нормально: глаз почти усредняет. А усилитель — честный прибор, он слышит прямоугольник целиком: и среднее, и всю рябь поверх.
На Uno нет цифро-аналогового преобразователя: analogWrite — это прямоугольник со скважностью, а не напряжение. Дешёвый мостик между цифровым пином и аналоговым миром — RC-фильтр: резистор и конденсатор, два элемента на копейки, которые превращают прямоугольник в его среднее значение. Резистор стоит в разрыве от пина, конденсатор — от узла на землю, потребитель снимает напряжение с конденсатора.
Разберём, почему на конденсаторе остаётся среднее, посчитаем постоянную времени и главный компромисс — гладкость против скорости, соберём управляемый источник опорного напряжения и честно оговорим, где этот трюк заканчивается и начинается настоящий ЦАП.
Среднее против пиков
analogWrite(9, 128) — это 128 тиков HIGH на каждые 255 тиков периода при частоте 490 Гц: период 2 миллисекунды, из них примерно половина — плюс. Среднее за период — 128/255 от 5 В, около 2,5 В. Светодиод это среднее честно показывает вполнакала; мультиметр в режиме V тоже покажет около 2,5 В безо всякого фильтра, потому что сам прибор тупит и усредняет — мой показал 2,47 В прямо на пине. А вот усилитель без фильтра слышит 490 Гц как грязь поверх нужного уровня.
RC-цепочка решает вопрос механикой заряда. Пока пин HIGH, конденсатор заряжается через резистор; пока LOW — разряжается через тот же резистор обратно в пин. Если за один период конденсатор не успевает ни зарядиться до пика, ни разрядиться до нуля, на нём живёт среднее с мелкой пилой — тем мельче, чем инертнее цепочка. Пила не исчезает никогда: при duty около половины и постоянной времени 0,1 с её размах — порядка десятков милливольт, мультиметр их не заметит, а осциллограф покажет честно.
Инертность цепочки — постоянная времени τ = R × C. Для ходовой пары 10 кОм и 10 мкФ: 10 000 × 0,00001 = 0,1 секунды. За одну τ выход доезжает до 63 процентов цели, за пять τ — до 99: полсекунды от щелчка ручки до установившегося напряжения. Период ШИМ 2 мс в пятьдесят раз короче τ — поэтому пила мелкая, а среднее держится уверенно. Сместите пропорцию — и либо пила вырастет (τ подъехала к периоду), либо отклик растянется на секунды.
Это тот же компромисс, что в фильтре питания, только там он про шину и провалы, здесь — про сигнал и точность. И тот же принцип нагрузки, что в делителе напряжения: потребитель на выходе фильтра должен тянуть ток хотя бы в десять раз меньше, чем идёт через резистор. При 2,5 В и 10 кОм через резистор идёт четверть миллиампера — значит, нагрузке положено не больше двух десятков микроампер. Вход усилителя и вход АЦП живут легко; лампочка — нет.
| R и C | τ | Скорость и пила | Для чего годится |
|---|---|---|---|
| 1 кОм + 10 мкФ | 0,01 с | доезжает за 50 мс, пила заметная | диммер светодиода, управление яркостью |
| 10 кОм + 10 мкФ | 0,1 с | полсекунды до цели, пила мелкая | опорное напряжение, громкость усилителя |
| 10 кОм + 100 мкФ | 1 с | гладко, но пять секунд ожидания | медленные опоры, смещение генератора |
| 100 кОм + 1 мкФ | 0,1 с | та же инертность, ток через R — микроамперы | сигнальные цепи с высоким входным сопротивлением |
const int PIN_POT = A0; // ручка задаёт уставкуconst int PIN_PWM = 9; // ШИМ-пин: сюда цепляем RC-фильтр void setup() { pinMode(PIN_PWM, OUTPUT); Serial.begin(9600); Serial.println("RC-filtr: ruchka na A0, PWM na D9, tau 0.1 s");} void loop() { int duty = analogRead(PIN_POT) / 4; // 0-1023 в 0-255 analogWrite(PIN_PWM, duty); long srednee = duty * 5000L / 255; // расчётное среднее в мВ Serial.print("duty="); Serial.print(duty); Serial.print(", srednee="); Serial.print(srednee); Serial.println(" mV"); delay(300);}Проверка прибором и границы трюка
Проверка мультиметром из урока про напряжение, ток и прозвонку: красный щуп на верхнюю обкладку конденсатора, чёрный на GND, режим V. Крутите ручку — прибор плавно пойдёт от десятков милливольт до почти пяти вольт, в среднем положении остановится около 2,5 В: ровно расчёт 128/255. Грабля проверки в том, что и без фильтра на пине 9 прибор покажет почти то же самое — он сам интегрирует. Отличить честное постоянное напряжение от ШИМ вольтметром нельзя: это услышит усилитель или покажет осциллограф.
Где трюк незаменим: плавная громкость на входе усилителя, опорное напряжение для сравнивателя, управление модулями с аналоговым входом. Где заканчивается: как только нужна форма волны — синус, свип, произвольная кривая — RC проигрывает мгновенно, потому что его скорость съедена τ. Тогда время настоящего ЦАП: MCP4725 по шине I2C даёт 12 бит, быстрый отклик и нулевую пилу за пару долларов. Моё рабочее правило: медленное постоянное напряжение — RC, повторяемая форма — ЦАП.
И последнее честное наблюдение: у крайних duty фильтр живёт хуже. При duty 5 и 250 конденсатор почти всё время либо заряжается, либо разряжается, пила растёт, и среднее держится с трудом. Диапазон 20-235 — рабочая зона; за её пределами трюк работает, но уже с оговорками.
В симуляторе ниже настоящего фильтра нет: движок рисует светодиод по duty, печатает расчётное среднее, а модель выхода ползёт к среднему шагами по 50 миллисекунд, повторяя доезд настоящего RC за пять τ. Настоящее напряжение в браузере не измеришь — на живой макетке это делает мультиметр по схеме выше. И примечание про пины: движок симулятора даёт ШИМ на любом выводе, а настоящая Uno умеет его только на 3, 5, 6, 9, 10 и 11 — для живой схемы фильтр ставьте на 9 или 10, пин 12 остаётся витриной яркости.
- analogWrite(9, 128) — прямоугольник 490 Гц со средним 128/255 × 5 В ≈ 2,5 В; глаз и мультиметр видят среднее, усилитель слышит пилу
- RC-фильтр: резистор от пина, конденсатор на землю; τ = R × C, 10 кОм × 10 мкФ = 0,1 с, доезд за 5τ ≈ 0,5 с
- Компромисс: больше τ — мельче пила, но медленнее отклик; период ШИМ должен оставаться много короче τ
- Нагрузка съедает фильтр: ток потребителя — десятая доля тока через резистор, дальше нужен буфер
- Медленное постоянное напряжение — RC; форма волны и скорость — настоящий ЦАП вроде MCP4725
- 1. Чему равно среднее напряжение на пине 9 при analogWrite(9, 128)?
- 2. Постоянная времени цепочки 10 кОм и 10 мкФ?
- 3. Мультиметр в режиме V на пине 9 без фильтра при duty 128 покажет...
- 4. Почему светодиод, повешенный прямо на выход RC-фильтра, портит картину?
- 5. Когда вместо RC-фильтра ставят ЦАП MCP4725?
Частые вопросы по теме урока
- Чему равно среднее напряжение на пине 9 при analogWrite(9, 128)?
- Скважность 128 из 255 умножаем на 5 В — примерно половина питания. Частота меняет тон пилы, а не среднее. около 2,5 В
- Постоянная времени цепочки 10 кОм и 10 мкФ?
- τ = R × C = 10 000 × 0,00001 = 0,1 с. За пять τ, полсекунды, выход доезжает до 99 процентов цели. 0,1 с: 10 000 × 0,00001
- Мультиметр в режиме V на пине 9 без фильтра при duty 128 покажет...
- Прибор тупит и усредняет, поэтому отличить ШИМ от честного постоянного напряжения вольтметром нельзя. ШИМ услышит усилитель или покажет осциллограф. около 2,5 В: прибор сам усредняет
- Почему светодиод, повешенный прямо на выход RC-фильтра, портит картину?
- Через 10 кОм идёт четверть миллиампера, светодиоду нужно на порядок больше — узел проседает. Нужно больше тока — ставьте буфер после фильтра. тянет больше тока, чем идёт через резистор, и просаживает узел
- Когда вместо RC-фильтра ставят ЦАП MCP4725?
- RC хорош для медленного постоянного напряжения, но его скорость съедена τ. Синус и быстрые кривые тянет только настоящий ЦАП с его 12 битами. когда нужны форма волны и быстрый отклик