ai: репозиторий переименован в eumirts5-dds; задание разделено на часть A (сборка DDS-стенда) и B (исследование интегратора, дифференциатора, RC-фильтра); stub синхронизирован с РПД (добавлен PIO-генератор); README с расшифровкой названия и картой пинов

This commit is contained in:
mss
2026-10-27 20:23:07 +04:00
parent 5087d1b348
commit 2c81de5d76
6 changed files with 1685 additions and 250 deletions
+97 -83
View File
@@ -1,116 +1,130 @@
# Лабораторная: интегратор и дифференциатор на ОУ (АЧХ/ФЧХ + Monte Carlo + автосвип) # ЭУМиРТС5-ДДС
Комплект к теме `topics/lab5-peredatochnaya-funkciya-na-ou.md` Репозиторий студента для одной лабораторной работы.
(«Электронные устройства мехатронных и робототехнических систем»,
Б1.В.06, 5 семестр, 4 ч).
> AI-сгенерировано (2026-10-26), требует проверки преподавателем **Дисциплина:** Электронные устройства мехатронных и робототехнических
> перед использованием на стенде. систем (ЭУМиРТС), Б1.В.06
**Специальность:** 15.03.06 «Мехатроника и робототехника»
**Семестр:** 5 · **Объём:** 4 часа
## Контракт Название репозитория расшифровывается так:
Оформлено по контракту `labs/`: | Часть | Значение |
|---|---|
| `eumirts` | ЭУМиРТС — электронные устройства мехатронных и робототехнических систем |
| `5` | пятый семестр |
| `dds` | Direct Digital Synthesis — генератор на RP2040, который вы собираете |
> Черновик. Требует проверки преподавателем перед выдачей студентам.
---
## О чём работа
Работа состоит из двух частей:
**A. Стенд.** Вы собираете DDS-генератор на RP2040 (Raspberry Pi Pico) и
скрипт автоматического снятия АЧХ. Готового лабораторного генератора со
свипом не оказалось, поэтому измерительный прибор делается своими руками.
**B. Исследование.** Этим стендом вы снимаете характеристики трёх схем —
интегратора на ОУ, дифференциатора на ОУ и пассивного RC-фильтра — и
сравниваете эксперимент с расчётом по передаточным функциям.
Полное задание — в **[task.md](task.md)**.
---
## Что в репозитории
``` ```
labs/lab5-peredatochnaya-funkciya-na-ou/ eumirts5-dds/
├── meta.yaml ← контракт
├── task.md ← задание студенту
├── method.md ← методичка преподавателю
├── README.md ← этот файл ├── README.md ← этот файл
├── print/ ← брошюры DOCX (rpd methodical) ├── task.md ← задание (части A и B)
└── stub/ ├── stub/ ← заготовки: генераторы и скрипт
├── 01-dds-generator-rp2040.ino ← генератор-свип (Arduino RP2040; │ ├── 01-dds-generator-rp2040.ino ← вариант 1: Arduino C++
│ оба ядра: earlephilhower и mbed) │ ├── 01-dds-generator-rp2040-circuitpython.py ← вариант 2: CircuitPython
├── 01-dds-generator-rp2040-circuitpython.py │ ├── 04-dds-pio-rp2040.py ← вариант 3: PIO + DMA
│ ← то же на CircuitPython (code.py) │ ├── 02-izmerenie-achh.py ← автоснятие АЧХ (на ПК)
├── 02-izmerenie-achh.py ← автоснятие АЧХ по Serial │ └── 03-blank-otchyota.md ← бланк отчёта
└── 03-blank-otchyota.md ← бланк отчёта студента └── print/ ← брошюра задания (DOCX)
``` ```
## Новое относительно `topics/lab5-peredatochnaya-funkciya-na-ou.md` ### Какой вариант генератора выбрать
1. **Monte Carlo по допускам** (`.step param`) — новый для курса анализ | Файл | Кому | Особенности |
в симуляторе: разброс K и f_c при ±5 % на компонентах, доля годных. |---|---|---|
2. **Генератор-свип на RP2040** — автономный генератор для натурной | `01-...ip2040.ino` | есть Arduino IDE | программный DDS, работает на обоих ядрах |
части: прямоугольник (ШИМ) и синус (DDS), логарифмический свип, | `01-...-circuitpython.py` | есть CircuitPython | то же, но медленнее (интерпретатор) |
синхроимпульс для осциллографа, измерение амплитуды на ADC0. | `04-dds-pio-rp2040.py` | **рекомендуется** | аппаратный PIO + DMA, точная частота, CPU свободен |
3. **Хост-скрипт автоснятия АЧХ** — управление генератором по Serial,
сбор точек, экспорт CSV, построение графика.
4. **Явное разделение практики и лаборатории:** симуляция — на практическом
занятии (2 ч), железо — на лабораторном (4 ч), отчёт — СРС.
## Предупреждения по стенду Для варианта на PIO нужна библиотека `adafruit_pioasm` в папке `/lib`
на плате.
- **ADC0 RP2040: 0…3,3 В.** Сигнал с выхода исследуемой цепи ≥ 3,3 В ---
подавать **только через делитель** или пиковый детектор.
- **Питание ОУ:** LM358 работает при однополярном +5…+12 В, TL081 —
при ±12 В. Уточнить по фактическому стенду.
- **Синус DDS:** качество зависит от внешнего ФНЧ после ШИМ (см. схему
ниже). Без фильтра на выходе будет меандр переменной скважности,
а не синус.
## Схема DDS-генератора (внешняя обвязка) ## Быстрый старт
ШИМ сам по себе даёт **меандр переменной скважности**, а не синус. 1. **Прошить генератор.** Файл переименовать в `code.py` (для CircuitPython)
Синус получается выделением огибающей фильтром. Поэтому на выходе или открыть в Arduino IDE (для `.ino`).
GP15 нужен внешний **ФНЧ**: 2. **Открыть консоль**, ввести `HELP` — увидеть список команд.
3. **Собрать ФНЧ** на выходе генератора (схема в `HELP`):
``` ```
GP15 (ШИМ 62,5 кГц) ──[R1 1к]──┬──[R2 1к]──┬──────► OUT (вход DUT) GP15 ──[R1 1к]──┬──[R2 1к]──┬──► к схеме
│ │ │ │
[C1 47н] [C2 47н] [C1 47н] [C2 47н]
│ │ │ │
GND GND GND GND
``` ```
Пассивный ФНЧ 2-го порядка, **f_c ≈ 3,4 кГц**: 4. **Проверить сигнал:** `W S` (синус), `F 1000`, посмотреть осциллографом
(период ≈ 1 мс).
5. **Калибровать частоту**, если нужно: ввести `CAL <измеренное_значение>`.
6. **Снять АЧХ** скриптом `02-izmerenie-achh.py` (запускается на ПК).
- подавление несущей: `(62,5 / 3,4)² ≈ 338 ≈ 50 дБ` → пульсации ≈ 10 мВ; ---
- рабочий диапазон генератора: **≈ 1 Гц … 1 кГц** (для звена
с f_c = 16…34 Гц — с запасом).
### Две оговорки ## Основные команды генератора
1. **Согласование сопротивлений.** Выход фильтра ≈ 1 кОм, вход | Команда | Что делает |
интегратора — R1 = 10 кОм → делитель 10/11, просадка ≈ 9 %. |---|---|
Если нужна точность — поставить буфер-повторитель на ОУ | `HELP` или `?` | подробная справка со всеми командами и схемой |
(**Sallen–Key**: тот же 2-й порядок + низкое выходное). | `I` | текущие настройки: частота, факт, потолок, `CPC` |
| `W S` / `W Q` | режим синуса / прямоугольника |
| `F <Гц>` | частота |
| `M <0..127>` | амплитуда синуса |
| `D <0..255>` | скважность прямоугольника |
| `A` | измерить размах на ADC0 (GP26) |
| `SWEEP f0 f1 n мс` | логарифмический свип |
| `B <1..8>` | число бит порта |
| `N <16..4096>` | длина периода в сэмплах |
| `O <1..64>` | точек на сэмпл |
| `CLC <1..8>` / `CAL <Гц>` | калибровка `CPC` вручную / автоматически |
| `FN <имя>` / `FP <выражение>` | форма сигнала из набора / своя формула |
2. **Постоянная составляющая.** При скважности 50 % среднее = `Uпит/2` ---
= 1,65 В, синус смещён. Где смещение недопустимо — разделительный
`C = 1 мкФ` последовательно + `R = 47 кОм` на землю (ФВЧ ≈ 3,4 Гц),
либо уменьшить амплитуду командой `M`.
### Варианты фильтра под другую несущую ## Пины стенда
| SAMPLE_HZ | R | C | f_c | | Пин | Назначение |
|---|---|---|---| |---|---|
| 62,5 кГц | 1 кОм | 47 нФ | 3,4 кГц | | GP8..GP15 | выход генератора (данные выровнены по старшему биту, MSB → GP15) |
| 62,5 кГц | 2,2 кОм | 22 нФ | 3,3 кГц | | GP15 | ШИМ в режиме прямоугольника (`W Q`) |
| 31,25 кГц | 2,2 кОм | 47 нФ | 1,5 кГц | | GP16 | синхроимпульс для осциллографа |
| GP26 (A0) | вход измерения ADC |
## Как использовать **Внимание:** на вход ADC подавать не более **3,3 В**. Сигнал больше —
только через делитель.
1. `task.md` + `stub/03-blank-otchyota.md` — студенту. ---
2. `stub/01-dds-generator-rp2040.ino` — прошить в RP2040 заранее
(или дать студенту в задании 4); альтернатива — `...-circuitpython.py`
на Pico с прошивкой CircuitPython (как `code.py`).
3. `stub/02-izmerenie-achh.py` — запускается на ПК студента (нужен pyserial).
4. `method.md` — только преподавателю.
5. Брошюры: `uv run rpd methodical lab5-peredatochnaya-funkciya-na-ou`.
## Связи ## Порядок сдачи
- **Практика** `pr5-raschet-analogovyh-ustrojstv` — расчётная часть 1. Собрать и откалибровать стенд (часть A).
(K, R1, R2, фильтры) выполняется там. 2. Снять характеристики трёх схем (часть B).
- **Лекция** `le5-metody-modelirovaniya` — типы анализа; Monte Carlo 3. Заполнить `stub/03-blank-otchyota.md`.
и `.step` — прямое применение. 4. Ответить на контрольные вопросы (в конце `task.md`).
- **Лекция** `le5-proektirovanie-analogovyh-ustrojstv` — топология ОУ.
- **ТАУ** (`b1-o-23`) — передаточные функции и типовые звенья идут
параллельно в 5 семестре; эта работа даёт им физическую реализацию.
## Статус Баллы по заданиям — в `task.md`, раздел «Оформление и оценивание».
Зачёт при **6 и более** баллах из 10.
Черновик (draft). Тема `lab5-peredatochnaya-funkciya-na-ou` существует
в `topics/`; комплект в `labs/` — подготовлен для интеграции после
проверки преподавателем и согласования сквозной работы по мехатронике.
+56 -4
View File
@@ -30,7 +30,7 @@
# M <0..127> — амплитуда синуса (127 = максимум) # M <0..127> — амплитуда синуса (127 = максимум)
# A — однократно измерить размах на ADC0 -> "A <мВ>" # A — однократно измерить размах на ADC0 -> "A <мВ>"
# SWEEP <f0> <f1> <n> <dwell_ms> # SWEEP <f0> <f1> <n> <dwell_ms>
# — логарифмический свип; "P <Гц> <мВ>" + импульс на GP14 # — логарифмический свип; "P <Гц> <мВ>" + импульс на GP16
# STOP — прервать свип # STOP — прервать свип
# #
# ─── СХЕМА СИНУСА (обязательна: ШИМ даёт меандр, а не синус) ─── # ─── СХЕМА СИНУСА (обязательна: ШИМ даёт меандр, а не синус) ───
@@ -55,7 +55,10 @@ import pwmio
import supervisor import supervisor
PIN_OUT = board.GP15 # выход сигнала (синус — через RC-фильтр) PIN_OUT = board.GP15 # выход сигнала (синус — через RC-фильтр)
PIN_TRIG = board.GP14 # синхроимпульс (для осциллографа) PIN_TRIG = board.GP16 # синхроимпульс. НЕ GP14: он входит в
# диапазон PIO (GP8..GP15) в варианте
# 04-dds-pio-rp2040.py; GP16 — единая
# разводка стенда для всех трёх вариантов
PIN_ADC = board.GP26 # ADC0 = A0 — вход измерения (через делителем) PIN_ADC = board.GP26 # ADC0 = A0 — вход измерения (через делителем)
CARRIER_HZ = 125000 # несущая ШИМ — много выше f_s, биений нет CARRIER_HZ = 125000 # несущая ШИМ — много выше f_s, биений нет
@@ -221,6 +224,52 @@ def trigger_pulse():
trig.value = False trig.value = False
def print_help():
"""Подробная справка по командам с форматами и примерами."""
lines = [
"# ─────────── DDS-генератор: команды ───────────",
"# Обозначения: <..> — обязательный аргумент.",
"# Команда вводится строкой, Enter — конец строки.",
"#",
"# РЕЖИМ И ЧАСТОТА",
"# W Q — режим прямоугольника (аппаратный ШИМ)",
"# W S — режим синуса (программный DDS -> ШИМ -> ФНЧ)",
"# F <Гц> — частота прямоугольника, 1..200000",
"# пример: F 1000",
"# SF <Гц> — частота СИНУСА, 1..f_s/2 (защита от алиасинга)",
"# пример: SF 25",
"#",
"# ФОРМА СИГНАЛА",
"# D <0..255> — скважность прямоугольника (128 = 50 %)",
"# пример: D 64 (25 % включено)",
"# M <0..127> — амплитуда синуса (127 = максимум)",
"# пример: M 32 (четверть шкалы)",
"#",
"# ИЗМЕРЕНИЕ И СВИП",
"# A — размах на ADC0 (GP26), мВ -> ответ 'A <мВ>'",
"# SWEEP <f0> <f1> <n> <dwell_ms>",
"# логарифмический свип f0..f1 за n точек,",
"# пауза dwell_ms на точку; печатает 'P <Гц> <мВ>',",
"# в конце 'DONE'",
"# пример: SWEEP 10 100000 25 150",
"# STOP — прервать свип",
"#",
"# СПРАВКА",
"# HELP | ? — этот текст",
"#",
"# ─── СХЕМА (синус: ШИМ даёт меандр, нужен ФНЧ) ───",
"# GP15 --[R1]--+--[R2]--+--> во вход схемы",
"# | |",
"# [C1] [C2] R1=R2=1к, C1=C2=47н",
"# | | (f_c подобрать под вашу f_s)",
"# GND GND",
"# Постоянная составляющая при 50% = Uпит/2. ADC0 — до 3.3 В (делитель!).",
"# ─────────────────────────────────────────────",
]
for ln in lines:
print(ln)
def handle(line, phase): def handle(line, phase):
"""Выполнить команду. Возвращает (ok, phase). Любые ошибки — внутрь.""" """Выполнить команду. Возвращает (ok, phase). Любые ошибки — внутрь."""
line = line.strip() line = line.strip()
@@ -229,7 +278,9 @@ def handle(line, phase):
parts = line.split(None, 1) # позиционно: sep=None, maxsplit=1 (в CP нет kwargs!) parts = line.split(None, 1) # позиционно: sep=None, maxsplit=1 (в CP нет kwargs!)
cmd = parts[0].upper() cmd = parts[0].upper()
a = parts[1] if len(parts) > 1 else "" a = parts[1] if len(parts) > 1 else ""
if cmd == "F": if cmd in ("HELP", "?"):
print_help()
elif cmd == "F":
cmd_f(a) cmd_f(a)
elif cmd == "SF": elif cmd == "SF":
cmd_sf(a) cmd_sf(a)
@@ -266,7 +317,8 @@ def calibrate_fs(phase):
# ─────────────────────────── main ───────────────────────────── # ─────────────────────────── main ─────────────────────────────
def main(): def main():
global fs_eff global fs_eff
print("# DDS generator ready (CircuitPython). help: F/W/D/A/SWEEP/STOP") print("# DDS generator ready (CircuitPython). Подробный хелп: HELP или ?")
print_help()
phase = 0 phase = 0
try: try:
fs_eff, phase = calibrate_fs(phase) fs_eff, phase = calibrate_fs(phase)
+55 -3
View File
@@ -80,7 +80,10 @@
// ─────────────────────────── пины ─────────────────────────── // ─────────────────────────── пины ───────────────────────────
#define PIN_OUT 15 // выход сигнала (прямоугольник — прямо; синус — через RC) #define PIN_OUT 15 // выход сигнала (прямоугольник — прямо; синус — через RC)
#define PIN_TRIG 14 // синхроимпульс (для осциллографа) #define PIN_TRIG 16 // синхроимпульс (для осциллографа)
// ВАЖНО: не GP14 — он попадает в диапазон PIO в
// варианте 04-dds-pio-rp2040.py; для единой разводки
// стенда синхро держим на GP16 во всех вариантах
#define PIN_ADC 26 // ADC0 = A0 — вход измерения (выход DUT через делитель!) #define PIN_ADC 26 // ADC0 = A0 — вход измерения (выход DUT через делитель!)
// ─────────────────────── параметры DDS ────────────────────── // ─────────────────────── параметры DDS ──────────────────────
@@ -269,12 +272,60 @@ static void runSweep(float f0, float f1, int n, uint32_t dwell_ms) {
setFrequency((uint32_t)f0); // вернуться к началу setFrequency((uint32_t)f0); // вернуться к началу
} }
// ─────────────────────── подробный хелп ──────────────────────
static void printHelp() {
Serial.println(F("# ─────────── DDS-генератор: команды ───────────"));
Serial.println(F("# Обозначения: <..> — обязательный аргумент."));
Serial.println(F("# Все команды вводятся строкой, Enter — конец строки."));
Serial.println(F("#"));
Serial.println(F("# РЕЖИМ И ЧАСТОТА"));
Serial.println(F("# W Q — режим прямоугольника (аппаратный ШИМ)"));
Serial.println(F("# W S — режим синуса (DDS -> ШИМ -> внешний ФНЧ)"));
Serial.println(F("# F <Гц> — частота выхода, 1..500000"));
Serial.println(F("# в режиме Q — частота прямоугольника;"));
Serial.println(F("# в режиме S — то же (для совместимости)"));
Serial.println(F("# пример: F 1000"));
Serial.println(F("# SF <Гц> — частота синуса с защитой от алиасинга"));
Serial.println(F("# ограничена SAMPLE_HZ/2 (см. шапку файла)"));
Serial.println(F("# пример: SF 25"));
Serial.println(F("#"));
Serial.println(F("# ФОРМА СИГНАЛА"));
Serial.println(F("# D <0..255> — скважность прямоугольника (128 = 50 %)"));
Serial.println(F("# пример: D 64 (25 % включено)"));
Serial.println(F("# M <0..127> — амплитуда синуса (127 = максимум)"));
Serial.println(F("# пример: M 32 (четверть шкалы)"));
Serial.println(F("#"));
Serial.println(F("# ИЗМЕРЕНИЕ И СВИП"));
Serial.println(F("# A — размах на ADC0 (GP26), мВ -> ответ 'A <мВ>'"));
Serial.println(F("# SWEEP <f0> <f1> <n> <dwell_ms>"));
Serial.println(F("# логарифмический свип от f0 до f1 за n точек,"));
Serial.println(F("# пауза dwell_ms на точку; на точку печатает"));
Serial.println(F("# 'P <Гц> <мВ>', в конце 'DONE'"));
Serial.println(F("# пример: SWEEP 10 100000 25 150"));
Serial.println(F("# STOP — прервать свип"));
Serial.println(F("#"));
Serial.println(F("# СПРАВКА"));
Serial.println(F("# HELP | ? — этот текст"));
Serial.println(F("#"));
Serial.println(F("# ─── СХЕМА (синус: ШИМ даёт меандр, нужен ФНЧ) ───"));
Serial.println(F("# GP15 --[R1]--+--[R2]--+--> во вход схемы"));
Serial.println(F("# | |"));
Serial.println(F("# [C1] [C2] R1=R2=1к, C1=C2=47н"));
Serial.println(F("# | | (f_c ~ 3.4 кГц)"));
Serial.println(F("# GND GND"));
Serial.println(F("# Постоянная составляющая при 50% = Uпит/2: нужен разделительный"));
Serial.println(F("# конденсатор, если смещение мешает. ADC0 — до 3.3 В (делитель!)."));
Serial.println(F("# ─────────────────────────────────────────────"));
}
// ─────────────────────── разбор команд ────────────────────── // ─────────────────────── разбор команд ──────────────────────
static void handleLine(char *line) { static void handleLine(char *line) {
char *cmd = strtok(line, " \t"); char *cmd = strtok(line, " \t");
if (!cmd) return; if (!cmd) return;
if (!strcasecmp(cmd, "F")) { if (!strcasecmp(cmd, "HELP") || !strcmp(cmd, "?")) {
printHelp();
} else if (!strcasecmp(cmd, "F")) {
char *a = strtok(nullptr, " \t"); char *a = strtok(nullptr, " \t");
if (a) setFrequency((uint32_t)strtoul(a, nullptr, 10)); if (a) setFrequency((uint32_t)strtoul(a, nullptr, 10));
Serial.print("OK F "); Serial.println(g_freq); Serial.print("OK F "); Serial.println(g_freq);
@@ -323,7 +374,8 @@ void setup() {
startSampleClock(); startSampleClock();
setMode(MODE_SQUARE); setMode(MODE_SQUARE);
setFrequency(1000); setFrequency(1000);
Serial.println("# DDS generator ready (RP2040). help: F/W/D/A/SWEEP/STOP"); Serial.println("# DDS generator ready (RP2040). Подробный хелп: HELP или ?");
printHelp();
} }
void loop() { void loop() {
File diff suppressed because it is too large Load Diff
+220 -163
View File
@@ -1,188 +1,240 @@
# Лабораторная работа # Лабораторная работа: DDS-стенд и исследование фильтров
## Интегратор и дифференциатор на ОУ: передаточная функция, АЧХ/ФЧХ и разброс по допускам ## Электронные устройства мехатронных и робототехнических систем
**Дисциплина:** Электронные устройства мехатронных и робототехнических **Дисциплина:** Электронные устройства мехатронных и робототехнических
систем (Б1.В.06, очная форма) систем, Б1.В.06
**Семестр:** 5 · **Объём:** 4 часа · **Тема:** `lab5-peredatochnaya-funkciya-na-ou` **Специальность:** 15.03.06 «Мехатроника и робототехника»
**Форма:** черновик — в учебный план пока не привязана **Семестр:** 5 · **Объём:** 4 часа
**Стенд:** RP2040 (Raspberry Pi Pico) + макетная плата
> AI-сгенерировано (2026-10-26), требует проверки преподавателем. > Черновик. Требует проверки преподавателем перед выдачей студентам.
--- ---
## 1. Легенда ## 1. Зачем эта работа
В мехатронном модуле сигнал датчика проходит через аналоговую обработку: В мехатронном модуле сигнал датчика проходит аналоговую обработку:
фильтрацию, интегрирование, выделение скорости (дифференцирование). фильтрацию помех, интегрирование, выделение скорости (дифференцирование).
Каждое такое звено описывается передаточной функцией, и от его параметров Каждое такое звено описывается передаточной функцией, и от его параметров
(K, τ) зависит поведение всей системы управления. (K, τ) зависит поведение всей системы управления.
**Задача работы:** убедиться, что аналоговое звено на операционном Чтобы **проверить звено на железе**, нужен генератор с известной частотой
усилителе действительно реализует расчётную передаточную функцию — сначала и амплитудой. Готового лабораторного генератора со свипом под рукой не
в симуляторе, затем на макетной плате. И понять, как **допуски** оказалось — поэтому в первой части работы вы **сами делаете стенд**:
резисторов и конденсаторов влияют на параметры звена в серии. DDS-генератор на RP2040 и скрипт автоматического снятия АЧХ.
Работа состоит из двух частей: Во второй части вы этим стендом **исследуете фильтры** — интегратор,
дифференциатор и RC-фильтр — и сравниваете эксперимент с расчётом.
- **Симуляция** (LTSpice): АЧХ/ФЧХ и **новый анализ — Monte Carlo** по допускам; ### Две части работы
- **Железо** (макет + генератор): переходные процессы и **автоматическое
снятие АЧХ** генератором-свипом на RP2040. | Часть | Что делаем | Результат |
|---|---|---|
| **A. Стенд** | собираем и настраиваем DDS-генератор | работающий прибор: частота, амплитуда, свип |
| **B. Исследование** | снимаем характеристики фильтров | АЧХ/ФЧХ, сравнение с расчётом |
Часть A без части B бессмысленна: прибор делается, чтобы им измерять.
Часть B без части A невозможна: нечем снимать АЧХ.
--- ---
## 2. Теория кратко ## 2. Теория кратко
**Интегратор на ОУ** (R1 на входе, C1 в ООС): ### 2.1. Что должен делать генератор (часть A)
**DDS** (Direct Digital Synthesis) — синтез сигнала из заранее
посчитанного массива значений. Идея:
1. считаем один период нужной формы — например синуса — в массив
из `m` точек;
2. подаём массив в PIO по кругу через DMA;
3. PIO выводит точки в порт с частотой `f_пио`;
4. частота выходного сигнала: `f_вых = f_пио / (CPC · m)`,
где `CPC` — число тактов PIO на один сэмпл.
Чем больше `m`, тем точнее форма и выше разрешение уровня, но тем ниже
максимальная частота.
### 2.2. Точность уровня: битность ≠ разрешение
- **Битность** `B` — сколько бит выводится в порт сразу (мгновенный код).
- **Эффективная разрядность** — сколько уровней различает **среднее**
после фильтра: `(2^B − 1)·m + 1`.
При `B = 4` и `m = 256` порт даёт 4 бита, но среднее различает
3841 уровень (~11.9 бит). Так работает дельта-сигма: соседние коды
чередуются во времени, а ФНЧ усредняет.
### 2.3. Интегратор на ОУ
**Идеальный** (R1 на входе, C1 в ООС):
```
W(s) = −1 / (R1·C1·s) W(s) = −1 / (R1·C1·s)
```
**Реальный интегратор** (резистор утечки R2 параллельно C1) — это На постоянном токе усиление бесконечно, поэтому **реальный** интегратор
всегда содержит резистор утечки R2 параллельно C1 — это превращает его в
**апериодическое звено первого порядка**: **апериодическое звено первого порядка**:
```
W(s) = −R2 / (R1 · (1 + R2·C1·s)) = −K / (τ·s + 1) W(s) = −R2 / (R1 · (1 + R2·C1·s)) = −K / (τ·s + 1)
K = R2/R1, τ = R2·C1, f_c = 1/(2π·τ)
```
где K = R2/R1, τ = R2·C1, f_c = 1/(2π·τ). ### 2.4. Дифференциатор на ОУ
**Дифференциатор** (C1 на входе, R1 в ООС): C1 на входе, R1 в ООС:
```
W(s) = −R1·C1·s W(s) = −R1·C1·s
```
**Модель для работы:** K = −10, τ = 10 мс, f_c ≈ 16 Гц На высоких частотах усиление растёт, поэтому на практике вход
(R1 = 10 кОм, R2 = 100 кОм, C1 = 0,1 мкФ). ограничивают резистором последовательно с C1.
### 2.5. RC-фильтр нижних частот
Пассивный ФНЧ первого порядка:
```
K(f) = 1 / √(1 + (f/f_c)²), f_c = 1/(2π·R·C)
наклон за f_c: −20 дБ/дек
```
--- ---
## 3. Задания ## 3. Часть A. Сборка и настройка стенда
### Задание 1 (1 ч). Симуляция: АЧХ и ФЧХ ### Задание A1 (0,5 ч). Прошивка генератора и первый запуск
В LTSpice собрать интегратор с резистором утечки: R1 = 10 кОм, В папке `stub/` три варианта генератора — **выберите один**:
R2 = 100 кОм, C1 = 0,1 мкФ (R2 || C1 в ООС).
1. Задать анализ `.ac dec 20 1 100k`. | Файл | Платформа | Как формируется синус |
2. Снять АЧХ в децибелах и ФЧХ. |---|---|---|
3. По графику определить: | `01-...ip2040.ino` | Arduino C++ | программный DDS + ШИМ |
- усиление на плоском участке (должно быть ≈ 20 дБ, т. е. K = 10); | `01-...-circuitpython.py` | CircuitPython | программный DDS + ШИМ |
- частоту сопряжения f_c (где спад −3 дБ); | `04-dds-pio-rp2040.py` | CircuitPython | **аппаратный PIO + DMA** |
- наклон спада (ожидается −20 дБ/дек).
4. Сравнить с расчётом по формулам из п. 2.
### Задание 2 (1 ч). Симуляция: Monte Carlo по допускам ⭐ **Рекомендуется вариант на PIO** — он даёт точную частоту и не грузит CPU.
**Новый анализ.** Реальные резисторы и конденсаторы имеют допуск ±5 % 1. Залейте файл на Pico (CircuitPython: переименовать в `code.py`).
(ряд E24 — не лучше). Оценим разброс параметров звена. 2. Откройте консоль, введите `HELP` — увидите список команд.
3. Введите `I` — генератор покажет текущие настройки, включая
**фактическую** частоту и потолок `f_max`.
4. Соберите внешний ФНЧ на выходе (схема — в `HELP`):
1. Задать разброс: `.step param tol list -5 -2.5 0 2.5 5` и применить ```
его к номиналам (например `{100k*(1+tol/100)}` для R2, аналогично R1 и C1). GP15 ──[R1 1к]──┬──[R2 1к]──┬──► выход
Либо, для полноценного статистического анализа, использовать
`.step param run 1 100 1` с генератором случайных отклонений.
2. Прогнать **не менее 100 прогонов**.
3. Для каждого прогона зафиксировать K (усиление на плоском участке) и f_c.
4. Построить гистограммы распределения K и f_c.
5. Посчитать **долю экземпляров**, укладывающихся в полосу ±10 % от
номинального значения K и f_c.
6. Сделать вывод: **какой компонент** вносит наибольший вклад в разброс
и почему.
### Задание 3 (1 ч). Железо: переходные процессы
Собрать на макетной плате:
**3.1. Интегратор** (R1 = 10 кОм, C1 = 0,1 мкФ):
- подать прямоугольник 1 кГц (от RP2040-генератора или лабораторного);
- наблюдать пилообразный сигнал на выходе;
- замерить размах пилы и сравнить с
U_m = U_вх · T / (2 · R1 · C1);
- убедиться, что при росте частоты размах падает обратно пропорционально.
**3.2. Дифференциатор** (C1 = 0,1 мкФ на входе, R1 = 10 кОм в ООС):
- подать пилу 1 кГц;
- наблюдать импульсы в моменты перепада;
- сравнить амплитуду с U_m = R1·C1 · dU_вх/dt.
**3.3. Роль резистора утечки:** собрать интегратор с R2 = 100 кОм
параллельно C1 и без него; объяснить, что меняется на постоянном токе.
### Задание 4 (1 ч). Железо: автоматическое снятие АЧХ
Использовать подготовленный генератор-свип:
- **`stub/01-dds-generator-rp2040.ino`** — прошить в RP2040 (Raspberry Pi
Pico) в Arduino IDE (работает в обоих ядрах: earlephilhower и официальном
mbed). Прямоугольник (ШИМ) и синус (DDS) + логарифмический свип
+ измерение амплитуды на ADC0.
- **`stub/01-dds-generator-rp2040-circuitpython.py`** — альтернатива без
Arduino: положить файл на Pico с прошивкой CircuitPython (переименовать
в code.py). Протокол команд тот же.
- **`stub/02-izmerenie-achh.py`** — хост-скрипт: запускает свип по Serial,
собирает точки, строит АЧХ.
Порядок:
1. Прошить генератор, проверить команды `F`, `W S`, `M`, `A` в мониторе
порта.
2. **Собрать внешний ФНЧ** на выходе генератора (без него будет меандр,
а не синус):
```
GP15 ──[R1 1к]──┬──[R2 1к]──┬──────► вход схемы
│ │ │ │
[C1 47н] [C2 47н] [C1 47н] [C2 47н]
│ │ │ │
GND GND GND GND
``` ```
Это пассивный ФНЧ 2-го порядка, f_c ≈ 3,4 кГц; он подавляет несущую **Проверка:** подать `W S` (синус), `F 1000`, посмотреть осциллографом.
ШИМ 62,5 кГц примерно на 50 дБ. **Зарисовать фильтр в отчёт.** Период должен быть ≈ 1 мс.
3. Выход фильтра → вход схемы; выход схемы → вход измерения (ADC0). ### Задание A2 (0,5 ч). Калибровка частоты
**Если сигнал превышает 3,3 В — только через делитель.**
4. Запустить: Частота зависит от `CPC` — числа тактов PIO на сэмпл. Оно может отличаться
``` на разных прошивках.
python 02-izmerenie-achh.py --port /dev/ttyACM0 \
1. Поставьте `F 1000`, измерьте период осциллографом.
2. Если факт отличается от запроса — введите `CAL <измеренное_значение>`,
например `CAL 500` при запросе 1000. Генератор подстроит `CPC` сам.
3. Повторите замер — теперь должно совпасть.
4. **Запишите** подобранное `CPC` (видно командой `I`) — оно нужно для
расчёта погрешности в отчёте.
> Если частота вообще не достижима, генератор скажет
> `! ЗАПРОС ВЫШЕ ПОТОЛКА: факт ... Гц`. Это значит `m` слишком велико:
> уменьшите `N` или `O`.
### Задание A3 (0,5 ч). Автоматическое снятие АЧХ
1. Соберите на макетной плате простой RC-фильтр (см. часть B, задание B3).
2. Подключите: выход генератора → вход фильтра; выход фильтра →
вход измерения (ADC0, GP26). **Если сигнал больше 3,3 В — через делитель.**
3. Запустите хост-скрипт:
```
python 02-izmerenie-achh.py --port /dev/ttyACM0 \
--f0 10 --f1 100000 --n 25 --dwell 150 --uin 500 --out achh.csv --plot --f0 10 --f1 100000 --n 25 --dwell 150 --uin 500 --out achh.csv --plot
``` ```
5. Импортировать CSV, нанести точки на модельную кривую из задания 1.
6. Объяснить расхождения.
> **Смещение:** при скважности 50 % среднее на выходе ШИМ = `Uпит/2` 4. Получите CSV с точками «частота → амплитуда». Это ваш измерительный
> = 1,65 В, поэтому синус смещён относительно земли. Если это мешает прибор на вторую часть работы.
> измерению — поставьте разделительный `C = 1 мкФ` + `R = 47 кОм`
> на землю, либо уменьшите амплитуду командой `M`.
> Свип-генератор — студенческая заготовка (черновик). Если на стенде **Результат части A:** работающий стенд, калиброванная частота, скрипт,
> есть серийный функциональный генератор с режимом свипа/логарифмической дающий АЧХ в CSV.
> развёртки — можно использовать его, принцип тот же.
### Задание 5 (СРС / отчёт). Сведение результатов
Свести в одну таблицу «**расчёт / симуляция / железо**» параметры
K, τ, f_c. Построить совмещённый график АЧХ (три кривые).
Сделать выводы:
- причины расхождения расчёта и симуляции;
- причины расхождения симуляции и железа;
- что даёт анализ Monte Carlo для реального проектирования.
--- ---
## 4. Варианты ## 4. Часть B. Исследование фильтров
| № | R1, кОм | R2, кОм | C1, мкФ | K | τ, мс | f_c, Гц | Все три задания выполняются **одним и тем же стендом**, меняется только
|---|---------|---------|---------|---|-------|---------| исследуемая схема. Для каждой схемы:
| 1 | 10 | 100 | 0,1 | 10 | 10 | 15,9 |
| 2 | 10 | 47 | 0,1 | 4,7 | 4,7 | 33,9 |
| 3 | 4,7 | 100 | 0,1 | 21 | 10 | 15,9 |
| 4 | 10 | 100 | 0,047 | 10 | 4,7 | 33,9 |
| 5 | 1 | 47 | 1,0 | 47 | 47 | 3,4 |
| 6 | 22 | 220 | 0,022 | 10 | 4,84 | 32,9 |
*Примечание. Номиналы приведены к ряду E24. Вариант 2 и 4 дают одинаковую 1. рассчитать параметры (K, τ или f_c) по формулам из п. 2;
f_c при разном K — удобно для сравнения вклада параметров.* 2. собрать схему на макетной плате;
3. снять АЧХ стендом (частичный диапазон вокруг f_c, 8–12 точек);
4. наложить экспериментальные точки на расчётную кривую;
5. оценить расхождение и объяснить его.
### Задание B1 (1 ч). Интегратор на ОУ
**Схема:** R1 = 10 кОм на вход, R2 = 100 кОм ‖ C1 = 0,1 мкФ в ООС.
- Рассчитать: `K = R2/R1`, `τ = R2·C1`, `f_c = 1/(2π·τ)`.
- Снять АЧХ в диапазоне **1 Гц … 10·f_c**.
- Определить по графику плоский участок, частоту сопряжения, наклон.
- **Проверить форму во времени:** подать прямоугольник, увидеть пилу.
Размах пилы `U_m = U_вх·T/(2·R1·C1)`.
**Контрольный вопрос:** почему `f_c` определяется `R2·C1`, а не `R1·C1`?
### Задание B2 (1 ч). Дифференциатор на ОУ
**Схема:** C1 = 0,1 мкФ на вход, R1 = 10 кОм в ООС.
- Рассчитать `W(s) = −R1·C1·s`, ожидаемый наклон **+20 дБ/дек**.
- Снять АЧХ в диапазоне, где схема ещё устойчива.
- **Проверить во времени:** подать пилу — увидеть импульсы в моменты
перепада. Амплитуда `U_m = R1·C1·dU_вх/dt`.
- Объяснить, почему реальный дифференциатор требует ограничения входа.
**Контрольный вопрос:** чем отличается идеальный дифференциатор от
реального и почему вход ограничивают резистором?
### Задание B3 (0,5 ч). Пассивный RC-фильтр
**Схема:** R = 1 кОм, C = 0,1 мкФ (или по вашему варианту).
- Рассчитать `f_c = 1/(2π·R·C)`, ожидаемый наклон −20 дБ/дек.
- Снять АЧХ стендом в диапазоне **0,1·f_c … 100·f_c** (10–12 точек).
- Наложить на расчётную кривую `K(f) = 1/√(1+(f/f_c)²)`.
- Сравнить расхождение с допусками компонентов (±5 %).
**Контрольный вопрос:** почему реальная АЧХ за `f_c` уходит круче
−20 дБ/дек? (подсказка: паразитные параметры, вход ADC)
### Задание B4 (0,5 ч). Сравнение и отчёт
Свести результаты трёх схем в таблицу:
| Схема | f_c расчёт | f_c опыт | Расхождение | Наклон расчёт | Наклон опыт |
|---|---|---|---|---|---|
| Интегратор | | | | −20 дБ/дек | |
| Дифференциатор | | | | +20 дБ/дек | |
| RC-фильтр | | | | −20 дБ/дек | |
Сделать выводы:
- какой разброс дали допуски компонентов;
- где опыт расходится с расчётом сильнее всего и почему;
- какую роль сыграла калибровка генератора (задание A2).
--- ---
@@ -190,51 +242,56 @@ f_c при разном K — удобно для сравнения вклад
Отчёт содержит: Отчёт содержит:
1. Схему интегратора и дифференциатора (KiCad или от руки). 1. Схемы: ФНЧ стенда, интегратор, дифференциатор, RC-фильтр.
2. АЧХ и ФЧХ из LTSpice. 2. Настройки генератора из `I` (включая `CPC` после калибровки).
3. Гистограммы Monte Carlo (K и f_c) + доля годных. 3. Осциллограммы: синус с генератора, пила интегратора, импульсы
4. Осциллограммы переходных процессов (пила, импульсы). дифференциатора.
5. CSV-точки автоматического свипа + совмещённый график АЧХ. 4. Три графика АЧХ с наложенными расчётными кривыми.
6. Итоговую таблицу «расчёт / симуляция / железо». 5. Итоговую таблицу из задания B4.
7. Выводы. 6. Выводы по расхождениям.
| Задание | Баллы | | Задание | Баллы |
|---------|-------| |---|---|
| 1. Симуляция АЧХ/ФЧХ | 2,0 | | A1. Прошивка и первый запуск | 1,0 |
| 2. Monte Carlo | 2,5 | | A2. Калибровка частоты | 1,0 |
| 3. Железо: переходные процессы | 2,0 | | A3. Автоснятие АЧХ | 2,0 |
| 4. Железо: автоснятие АЧХ | 2,0 | | B1. Интегратор | 2,0 |
| 5. Отчёт: сведение | 1,5 | | B2. Дифференциатор | 2,0 |
| B3. RC-фильтр | 1,0 |
| B4. Сводка и выводы | 1,0 |
| **Итого** | **10** | | **Итого** | **10** |
Зачёт — при **6 и более** баллах. Расхождение с эталоном ±10 % Зачёт — при **6 и более** баллах.
(допуски компонентов).
--- ---
## 6. Контрольные вопросы ## 6. Контрольные вопросы
1. Чему равна передаточная функция идеального интегратора и почему без **По стенду (часть A):**
резистора утечки она нереализуема на практике?
2. Как по АЧХ отличить идеальный интегратор от апериодического звена 1. Чему равна частота выходного сигнала DDS и какие величины её задают?
первого порядка? 2. Что такое `CPC` и почему его приходится калибровать?
3. Почему частота сопряжения определяется R2·C1, а не R1·C1? 3. Чем битность порта отличается от эффективной разрядности?
4. Как связаны наклон АЧХ в дБ/дек и порядок звена? 4. Почему для синуса нужен внешний ФНЧ после ШИМ?
5. Какой компонент даёт наибольший вклад в разброс f_c при допуске ±5 %
и почему? **По фильтрам (часть B):**
6. Как на форме переходного процесса сказывается конечная полоса
пропускания операционного усилителя? 5. Чему равна передаточная функция идеального интегратора и почему без
резистора утечки её нельзя реализовать?
6. Как по АЧХ отличить идеальный интегратор от апериодического звена?
7. Почему наклон АЧХ звена первого порядка равен −20 дБ/дек?
8. Как допуски R и C влияют на `f_c` и что даёт анализ Monte Carlo?
--- ---
## 7. Литература ## 7. Литература
1. Хоровиц П., Хилл У. Искусство схемотехники. 3-е изд. М.: Бином, 2014. 1. Хоровиц П., Хилл У. Искусство схемотехники. 3-е изд. М.: Бином, 2014.
Гл. 4. Гл. 4 (ОУ в линейном режиме).
2. Титце У., Шенк К. Полупроводниковая схемотехника. 12-е изд. М.: ДМК 2. Титце У., Шенк К. Полупроводниковая схемотехника. 12-е изд. М.: ДМК
Пресс, 2008. Т. 1, гл. 11. Пресс, 2008. Т. 1, гл. 11 (частотные характеристики).
3. Бесекерский В.А., Попов Е.П. Теория систем автоматического 3. Бесекерский В.А., Попов Е.П. Теория систем автоматического
регулирования. М.: Наука, 2010. Гл. 2. регулирования. М.: Наука, 2010. Гл. 2 (типовые звенья).
4. LTSpice XVII User Guide. Analog Devices. 4. LTSpice XVII User Guide. Analog Devices.
5. LM358 / TL081 datasheet. Texas Instruments. 5. RP2040 Datasheet. Raspberry Pi Ltd (PIO, DMA, ADC).
6. RP2040 Datasheet. Raspberry Pi Ltd. 6. LM358 / TL081 datasheet. Texas Instruments.