commit 45d6982d17c468a2a734b2898ad116d8b82e5f3f Author: mss Date: Mon Oct 26 15:19:12 2026 +0400 ai: студенческая копия лабораторной 5 (DDS-генератор RP2040 + АЧХ интегратора) из РПД diff --git a/README.md b/README.md new file mode 100644 index 0000000..a116da8 --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +# Лабораторная: интегратор и дифференциатор на ОУ (АЧХ/ФЧХ + Monte Carlo + автосвип) + +Комплект к теме `topics/lab5-peredatochnaya-funkciya-na-ou.md` +(«Электронные устройства мехатронных и робототехнических систем», +Б1.В.06, 5 семестр, 4 ч). + +> AI-сгенерировано (2026-10-26), требует проверки преподавателем +> перед использованием на стенде. + +## Контракт + +Оформлено по контракту `labs/`: + +``` +labs/lab5-peredatochnaya-funkciya-na-ou/ +├── meta.yaml ← контракт +├── task.md ← задание студенту +├── method.md ← методичка преподавателю +├── README.md ← этот файл +├── print/ ← брошюры DOCX (rpd methodical) +└── stub/ + ├── 01-dds-generator-rp2040.ino ← генератор-свип (Arduino, RP2040) + ├── 02-izmerenie-achh.py ← автоснятие АЧХ по Serial + └── 03-blank-otchyota.md ← бланк отчёта студента +``` + +## Новое относительно `topics/lab5-peredatochnaya-funkciya-na-ou.md` + +1. **Monte Carlo по допускам** (`.step param`) — новый для курса анализ + в симуляторе: разброс K и f_c при ±5 % на компонентах, доля годных. +2. **Генератор-свип на RP2040** — автономный генератор для натурной + части: прямоугольник (ШИМ) и синус (DDS), логарифмический свип, + синхроимпульс для осциллографа, измерение амплитуды на ADC0. +3. **Хост-скрипт автоснятия АЧХ** — управление генератором по Serial, + сбор точек, экспорт CSV, построение графика. +4. **Явное разделение практики и лаборатории:** симуляция — на практическом + занятии (2 ч), железо — на лабораторном (4 ч), отчёт — СРС. + +## Предупреждения по стенду + +- **ADC0 RP2040: 0…3,3 В.** Сигнал с выхода исследуемой цепи ≥ 3,3 В + подавать **только через делитель** или пиковый детектор. +- **Питание ОУ:** LM358 работает при однополярном +5…+12 В, TL081 — + при ±12 В. Уточнить по фактическому стенду. +- **Синус DDS:** качество зависит от внешнего ФНЧ после ШИМ (см. схему + ниже). Без фильтра на выходе будет меандр переменной скважности, + а не синус. + +## Схема DDS-генератора (внешняя обвязка) + +ШИМ сам по себе даёт **меандр переменной скважности**, а не синус. +Синус получается выделением огибающей фильтром. Поэтому на выходе +GP15 нужен внешний **ФНЧ**: + +``` +GP15 (ШИМ 62,5 кГц) ──[R1 1к]──┬──[R2 1к]──┬──────► OUT (вход DUT) + │ │ + [C1 47н] [C2 47н] + │ │ + GND GND +``` + +Пассивный ФНЧ 2-го порядка, **f_c ≈ 3,4 кГц**: + +- подавление несущей: `(62,5 / 3,4)² ≈ 338 ≈ 50 дБ` → пульсации ≈ 10 мВ; +- рабочий диапазон генератора: **≈ 1 Гц … 1 кГц** (для звена + с f_c = 16…34 Гц — с запасом). + +### Две оговорки + +1. **Согласование сопротивлений.** Выход фильтра ≈ 1 кОм, вход + интегратора — R1 = 10 кОм → делитель 10/11, просадка ≈ 9 %. + Если нужна точность — поставить буфер-повторитель на ОУ + (**Sallen–Key**: тот же 2-й порядок + низкое выходное). + +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 кГц | +| 62,5 кГц | 2,2 кОм | 22 нФ | 3,3 кГц | +| 31,25 кГц | 2,2 кОм | 47 нФ | 1,5 кГц | + +## Как использовать + +1. `task.md` + `stub/03-blank-otchyota.md` — студенту. +2. `stub/01-dds-generator-rp2040.ino` — прошить в RP2040 заранее + (или дать студенту в задании 4). +3. `stub/02-izmerenie-achh.py` — запускается на ПК студента (нужен pyserial). +4. `method.md` — только преподавателю. +5. Брошюры: `uv run rpd methodical lab5-peredatochnaya-funkciya-na-ou`. + +## Связи + +- **Практика** `pr5-raschet-analogovyh-ustrojstv` — расчётная часть + (K, R1, R2, фильтры) выполняется там. +- **Лекция** `le5-metody-modelirovaniya` — типы анализа; Monte Carlo + и `.step` — прямое применение. +- **Лекция** `le5-proektirovanie-analogovyh-ustrojstv` — топология ОУ. +- **ТАУ** (`b1-o-23`) — передаточные функции и типовые звенья идут + параллельно в 5 семестре; эта работа даёт им физическую реализацию. + +## Статус + +Черновик (draft). Тема `lab5-peredatochnaya-funkciya-na-ou` существует +в `topics/`; комплект в `labs/` — подготовлен для интеграции после +проверки преподавателем и согласования сквозной работы по мехатронике. diff --git a/print/methodical-lab5-peredatochnaya-funkciya-na-ou-student.docx b/print/methodical-lab5-peredatochnaya-funkciya-na-ou-student.docx new file mode 100644 index 0000000..16305c2 Binary files /dev/null and b/print/methodical-lab5-peredatochnaya-funkciya-na-ou-student.docx differ diff --git a/stub/01-dds-generator-rp2040.ino b/stub/01-dds-generator-rp2040.ino new file mode 100644 index 0000000..e0b5f73 --- /dev/null +++ b/stub/01-dds-generator-rp2040.ino @@ -0,0 +1,243 @@ +/* + * DDS-генератор сигналов для лабораторных работ + * Платформа: RP2040 (Raspberry Pi Pico, Arduino core — earlephilhower) + * + * ЧЕРНОВИК (AI-сгенерировано, 2026-10-26). Требует проверки преподавателем + * на реальном стенде: номиналы RC-фильтра, диапазоны частот, точность ADC. + * + * Возможности: + * - прямоугольник : аппаратный ШИМ, точная частота, независимая скважность; + * - синус : таблица 256 точек + аккумулятор фазы (DDS) в таймерном + * ISR -> ШИМ (несущая = SAMPLE_HZ = 62,5 кГц) -> внешний + * ФНЧ (схема ниже); амплитуда — командой M; + * - свип : логарифмический (f0..f1, N точек) с синхроимпульсом + * на отдельном пине — для осциллографа/хост-скрипта; + * - измерение : ADC0 (размах за окно) — амплитуда на выходе + * исследуемой цепи (DUT) для автоматической АЧХ. + * + * ─── СХЕМА СИНУСА (обязательна: ШИМ даёт меандр, а не синус) ─── + * + * GP15 ──[R1]──┬──[R2]──┬──────► OUT (вход DUT) + * │ │ + * [C1] [C2] + * │ │ + * GND GND + * + * Пассивный ФНЧ 2-го порядка. При несущей 62,5 кГц: + * R1 = R2 = 1 кОм, C1 = C2 = 47 нФ -> f_c ≈ 3,4 кГц + * подавление несущей ≈ (62,5/3,4)^2 ≈ 50 дБ -> пульсации ~10 мВ + * Номиналы для другой несущей: f_c и постоянную RC смотреть в README. + * + * ВНИМАНИЕ (важно): выходное сопротивление фильтра ~1 кОм. Вход + * интегратора — R1 = 10 кОм, получается делитель 10/11 (просадка ~9 %). + * Если это критично — поставить буфер-повторитель на ОУ (Sallen-Key): + * тот же фильтр 2-го порядка + низкое выходное сопротивление. + * + * Постоянная составляющая: при скважности 50 % среднее = 1,65 В, синус + * смещён на Uпит/2. Где смещение недопустимо — разделительный C = 1 мкФ + * последовательно + R = 47 кОм на землю (ФВЧ ≈ 3,4 Гц), либо уменьшить + * амплитуду командой M. + * + * Протокол команд (Serial, 115200, строка + \n): + * F <Гц> — установить частоту (1..500000) + * W Q | W S — режим: Q — прямоугольник, S — синус + * D <0..255> — скважность прямоугольника (128 = 50 %) + * M <0..127> — амплитуда синуса (127 = максимум) + * A — однократно измерить амплитуду на ADC0 + * -> ответ "A <мВ размах>" + * SWEEP + * — логарифмический свип; на каждой точке выдаёт + * "P <Гц> <мВ>" и импульс синхро на PIN_TRIG + * STOP — прервать свип + */ + +#include +#include + +// ─────────────────────────── пины ─────────────────────────── +#define PIN_OUT 15 // выход сигнала (прямоугольник — прямо; синус — через RC) +#define PIN_TRIG 14 // синхроимпульс (для осциллографа) +#define PIN_ADC 26 // ADC0 = A0 — вход измерения (выход DUT через делитель!) + +// ─────────────────────── параметры DDS ────────────────────── +// ВАЖНО: несущая ШИМ и частота обновления выборок должны СОВПАДАТЬ. +// Значение скважности применяется один раз за период ШИМ; если обновлять +// выборки с другой частотой, появляется джиттер и биения на выходе фильтра. +// При 16 мкс период ISR занимает ~3 % CPU RP2040; при перегрузке — +// снизить до 31250 (тогда f_c фильтра пересчитать вниз пропорционально). +#define CARRIER_HZ 62500UL // несущая ШИМ для синуса (= частота выборок) +#define SAMPLE_HZ 62500UL // частота обновления выборок синуса +#define PWM_RANGE 255 // 8-бит (для синуса); прямоугольнику хватает +#define AMP_MAX 127 // максимальная амплитуда выборки (единиц duty) + +// ───────────────────────── состояние ──────────────────────── +enum WaveMode : uint8_t { MODE_SQUARE = 0, MODE_SINE = 1 }; + +static volatile uint32_t g_freq = 1000; // текущая частота, Гц +static volatile uint8_t g_duty = 128; // 0..255 (прямоугольник) +static volatile uint8_t g_amp = AMP_MAX;// амплитуда синуса, 0..AMP_MAX +static volatile WaveMode g_mode = MODE_SQUARE; +static volatile uint32_t g_phase = 0; // аккумулятор фазы (32 бит) +static volatile bool g_sweep = false; // флаг активного свипа +static int8_t g_lut[256]; // sin: -127..127 + +// ─────────────────────── таблица синуса ───────────────────── +static void buildLut() { + for (int i = 0; i < 256; ++i) { + g_lut[i] = (int8_t)lroundf(127.0f * sinf(2.0f * (float)M_PI * i / 256.0f)); + } +} + +// ───────────── ISR: обновление ШИМ для синуса (DDS) ───────── +static bool onSample(repeating_timer_t *) { + if (g_mode == MODE_SINE) { + // шаг фазы = f * 2^32 / Fs (64-бит, чтобы не переполнить) + uint32_t step = + (uint32_t)((uint64_t)g_freq * (1ULL << 32) / SAMPLE_HZ); + g_phase += step; + uint8_t idx = (uint8_t)(g_phase >> 24); + // центрируем на 128 и масштабируем амплитудой (g_amp 0..127) + int32_t s = ((int32_t)g_lut[idx] * g_amp) / 127; + analogWrite(PIN_OUT, (uint8_t)(128 + s)); + } + return true; +} + +static repeating_timer_t g_timer; + +// ─────────────────── применить режим/частоту ──────────────── +static void applySquare() { + analogWriteFreq(g_freq); + analogWriteRange(PWM_RANGE); + // после analogWriteFreq/analogWriteRange текущее значение сбрасывается: + analogWrite(PIN_OUT, g_duty); +} + +static void applySine() { + // частота ШИМ = SAMPLE_HZ (совпадает с ISR), размах — 8 бит + analogWriteFreq(CARRIER_HZ); + analogWriteRange(PWM_RANGE); +} + +static void setFrequency(uint32_t hz) { + if (hz < 1) hz = 1; + if (hz > 500000) hz = 500000; + g_freq = hz; + if (g_mode == MODE_SQUARE) applySquare(); +} + +static void setMode(WaveMode m) { + g_mode = m; + if (m == MODE_SQUARE) applySquare(); + else applySine(); +} + +// ─────────────────── измерение амплитуды (ADC) ────────────── +// Возвращает размах (пик-пик) в милливольтах за окно window_ms. +// TODO (студенту): заменить окно по времени на окно по числу периодов +// измеряемой частоты, чтобы размах считался по целому числу периодов. +static uint32_t measureAmplitudeMv(uint32_t window_ms = 50) { + uint16_t vmin = 4095, vmax = 0; + uint32_t t0 = millis(); + while ((millis() - t0) < window_ms) { + uint16_t v = analogRead(PIN_ADC); + if (v < vmin) vmin = v; + if (v > vmax) vmax = v; + } + // ADC 12 бит, Vref = 3,3 В + return (uint32_t)((uint32_t)(vmax - vmin) * 3300UL / 4095UL); +} + +// ───────────────────────── свип ───────────────────────────── +static void triggerPulse() { + digitalWrite(PIN_TRIG, HIGH); + delayMicroseconds(50); + digitalWrite(PIN_TRIG, LOW); +} + +static void runSweep(float f0, float f1, int n, uint32_t dwell_ms) { + if (n < 2) n = 2; + if (f0 < 1) f0 = 1; + if (f1 <= f0) f1 = f0 * 10.0f; + g_sweep = true; + + const float ratio = powf(f1 / f0, 1.0f / (float)(n - 1)); + float f = f0; + for (int i = 0; i < n && g_sweep; ++i) { + setFrequency((uint32_t)lroundf(f)); + triggerPulse(); // метка точки для осциллографа + delay(dwell_ms); // дать DUT/фильтру устояться + uint32_t mv = measureAmplitudeMv(); + Serial.print("P "); // точка АЧХ: частота + размах + Serial.print((uint32_t)lroundf(f)); + Serial.print(' '); + Serial.println(mv); + f *= ratio; + } + Serial.println("DONE"); + setFrequency((uint32_t)f0); // вернуться к началу +} + +// ─────────────────────── разбор команд ────────────────────── +static void handleLine(char *line) { + char *cmd = strtok(line, " \t"); + if (!cmd) return; + + if (!strcasecmp(cmd, "F")) { + char *a = strtok(nullptr, " \t"); + if (a) setFrequency((uint32_t)strtoul(a, nullptr, 10)); + Serial.print("OK F "); Serial.println(g_freq); + } else if (!strcasecmp(cmd, "W")) { + char *a = strtok(nullptr, " \t"); + if (a) setMode((!strcasecmp(a, "S")) ? MODE_SINE : MODE_SQUARE); + Serial.print("OK W "); Serial.println(g_mode == MODE_SINE ? "S" : "Q"); + } else if (!strcasecmp(cmd, "D")) { + char *a = strtok(nullptr, " \t"); + if (a) { g_duty = (uint8_t)constrain(atoi(a), 0, 255); applySquare(); } + Serial.print("OK D "); Serial.println(g_duty); + } else if (!strcasecmp(cmd, "M")) { + char *a = strtok(nullptr, " \t"); + if (a) g_amp = (uint8_t)constrain(atoi(a), 0, AMP_MAX); + Serial.print("OK M "); Serial.println(g_amp); + } else if (!strcasecmp(cmd, "A")) { + Serial.print("A "); Serial.println(measureAmplitudeMv()); + } else if (!strcasecmp(cmd, "SWEEP")) { + char *a0 = strtok(nullptr, " \t"); + char *a1 = strtok(nullptr, " \t"); + char *a2 = strtok(nullptr, " \t"); + char *a3 = strtok(nullptr, " \t"); + if (a0 && a1 && a2 && a3) { + runSweep(atof(a0), atof(a1), atoi(a2), strtoul(a3, nullptr, 10)); + } + } else if (!strcasecmp(cmd, "STOP")) { + g_sweep = false; + } +} + +// ────────────────────────── setup/loop ────────────────────── +void setup() { + Serial.begin(115200); + buildLut(); + pinMode(PIN_TRIG, OUTPUT); + digitalWrite(PIN_TRIG, LOW); + analogReadResolution(12); // ADC0 — 12 бит + add_repeating_timer_us(-(1000000L / SAMPLE_HZ), onSample, nullptr, &g_timer); + setMode(MODE_SQUARE); + setFrequency(1000); + Serial.println("# DDS generator ready (RP2040). help: F/W/D/A/SWEEP/STOP"); +} + +void loop() { + static char buf[96]; + static size_t len = 0; + while (Serial.available()) { + char c = (char)Serial.read(); + if (c == '\n' || c == '\r') { + buf[len] = '\0'; + if (len) handleLine(buf); + len = 0; + } else if (len < sizeof(buf) - 1) { + buf[len++] = c; + } + } +} diff --git a/stub/02-izmerenie-achh.py b/stub/02-izmerenie-achh.py new file mode 100644 index 0000000..fcb3ca4 --- /dev/null +++ b/stub/02-izmerenie-achh.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +""" +Хост-скрипт: автоматическое снятие АЧХ с DDS-генератора (RP2040). + +ЧЕРНОВИК (AI-сгенерировано, 2026-10-26). Требует проверки преподавателем. + +Управляет генератором 01-dds-generator-rp2040.ino по Serial, запускает +логарифмический свип, собирает точки "P <Гц> <мВ>" и строит АЧХ в дБ. + +Использование: + python 02-izmerenie-achh.py --port /dev/ttyACM0 \ + --f0 10 --f1 100000 --n 25 --dwell 150 --out achh.csv + +Зависимости: pyserial (обязательно), matplotlib (опционально, для графика). + pip install pyserial matplotlib + +ПРОТОКОЛ (строки, \n): + -> W S режим синуса + -> SWEEP + <- P <Гц> <мВ> точка АЧХ + <- DONE свип завершён + +ВНИМАНИЕ: вход ADC0 генератора — 0..3,3 В. Сигнал с выхода исследуемой +цепи выше 3,3 В подавать только через делитель/пиковый детектор. +Нормировка на выходе: gain_dB = 20*log10(Uout/Uin). Входное напряжение +Uin берётся из аргумента --uin (действующая или амплитудная — как задано, +скрипт работает с размахом, мВ). +""" + +from __future__ import annotations + +import argparse +import csv +import math +import sys +import time + +try: + import serial # type: ignore +except ImportError: # pragma: no cover + print("Нужен pyserial: pip install pyserial", file=sys.stderr) + raise SystemExit(2) + + +def open_port(port: str, baud: int = 115200, timeout: float = 0.2): + return serial.Serial(port, baud, timeout=timeout) + + +def send(ser, line: str) -> None: + ser.write((line + "\n").encode("ascii")) + ser.flush() + + +def collect_sweep(ser, f0: float, f1: float, n: int, dwell: int, + uin_mv: float, timeout_s: float = 120.0): + """Запустить свип и вернуть список (f, uout_mv, gain_db).""" + send(ser, "W S") # синус + time.sleep(0.2) + send(ser, f"SWEEP {f0:.3f} {f1:.3f} {n} {dwell}") + + points: list[tuple[float, float, float]] = [] + t0 = time.time() + while True: + if time.time() - t0 > timeout_s: + print("таймаут свипа", file=sys.stderr) + break + raw = ser.readline().decode("ascii", "replace").strip() + if not raw: + continue + if raw == "DONE": + break + if raw.startswith("P "): + _, fs, mv = raw.split() + f = float(fs) + uout = float(mv) + gain = 20.0 * math.log10(max(uout, 1e-6) / max(uin_mv, 1e-6)) + points.append((f, uout, gain)) + print(f" {f:>9.1f} Гц {uout:>7.1f} мВ {gain:+6.2f} дБ") + return points + + +def write_csv(path: str, points) -> None: + with open(path, "w", newline="", encoding="utf-8") as fh: + w = csv.writer(fh) + w.writerow(["freq_hz", "uout_mv", "gain_db"]) + for row in points: + w.writerow([f"{row[0]:.3f}", f"{row[1]:.3f}", f"{row[2]:.4f}"]) + print(f"CSV: {path}") + + +def plot(points) -> None: + try: + import matplotlib.pyplot as plt # type: ignore + except ImportError: + print("matplotlib нет — график пропущен (CSV сохранён)", file=sys.stderr) + return + xs = [p[0] for p in points] + ys = [p[2] for p in points] + plt.semilogx(xs, ys, "o-") + plt.xlabel("Частота, Гц") + plt.ylabel("Усиление, дБ") + plt.grid(True, which="both") + plt.title("АЧХ (автоснятие с RP2040 DDS)") + plt.tight_layout() + plt.show() + + +def main() -> int: + ap = argparse.ArgumentParser(description="Автоснятие АЧХ через RP2040 DDS") + ap.add_argument("--port", required=True, help="например /dev/ttyACM0 или COM5") + ap.add_argument("--f0", type=float, default=10.0) + ap.add_argument("--f1", type=float, default=100000.0) + ap.add_argument("--n", type=int, default=25) + ap.add_argument("--dwell", type=int, default=150, help="мс на точку") + ap.add_argument("--uin", type=float, default=500.0, + help="входное напряжение (размах), мВ") + ap.add_argument("--out", default="achh.csv") + ap.add_argument("--plot", action="store_true") + args = ap.parse_args() + + ser = open_port(args.port) + time.sleep(0.5) + ser.reset_input_buffer() + try: + points = collect_sweep(ser, args.f0, args.f1, args.n, args.dwell, args.uin) + finally: + ser.close() + if not points: + print("точек не получено", file=sys.stderr) + return 1 + write_csv(args.out, points) + if args.plot: + plot(points) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/stub/03-blank-otchyota.md b/stub/03-blank-otchyota.md new file mode 100644 index 0000000..d308d52 --- /dev/null +++ b/stub/03-blank-otchyota.md @@ -0,0 +1,150 @@ +# Бланк отчёта — интегратор/дифференциатор на ОУ + +Лабораторная `lab5-peredatochnaya-funkciya-na-ou`, 4 ч. +ФИО / группа / вариант: _____________________________ + +> Файл заполняется студентом. Все значения — с единицами измерения. + +--- + +## 1. Параметры варианта + +| Параметр | Значение | +|---|---| +| R1 | кОм | +| R2 | кОм | +| C1 | мкФ | +| U_пит | ± В | + +**Расчёт (до эксперимента):** + +- K = R2/R1 = _____ +- τ = R2·C1 = _____ мс +- f_c = 1/(2π·τ) = _____ Гц + +--- + +## 2. Симуляция: АЧХ/ФЧХ (задание 1) + +Директива: `.ac dec 20 1 100k` + +| Параметр | Расчёт | Из симуляции | Расхождение | +|---|---|---|---| +| Усиление на плоском участке, дБ | | | | +| f_c, Гц | | | | +| Наклон за f_c, дБ/дек | −20 | | | + +Вставить графики АЧХ и ФЧХ ↓ + +``` +(место для скриншота LTSpice) +``` + +--- + +## 3. Monte Carlo (задание 2) + +Директивы: + +``` +.step param tol ... +``` + +Число прогонов: ____ + +| Параметр | Среднее | СКО | Мин | Макс | Доля в ±10 % | +|---|---|---|---|---|---| +| K | | | | | | +| f_c, Гц | | | | | | + +Гистограммы ↓ + +``` +(место для гистограмм) +``` + +**Вывод о вкладе компонентов:** + +- + +--- + +## 4. Железо: переходные процессы (задание 3) + +### 4.1. Интегратор (прямоугольник 1 кГц) + +| Параметр | Расчёт | Измерение | +|---|---|---| +| Размах пилы U_m, В | | | +| Частота входного сигнала, кГц | 1,0 | | + +Осциллограмма ↓ + +``` +(место для осциллограммы) +``` + +### 4.2. Дифференциатор (пила 1 кГц) + +| Параметр | Расчёт | Измерение | +|---|---|---| +| Амплитуда импульса, В | | | + +### 4.3. Роль резистора утечки + +Что меняется без R2: ______________________________ + +--- + +## 5. Железо: автоснятие АЧХ (задание 4) + +Команда запуска: + +``` +python 02-izmerenie-achh.py --port ____ --f0 10 --f1 100000 --n 25 --dwell 150 --uin ___ --out achh.csv +``` + +Таблица точек (первые 5 и последние 5): + +| f, Гц | U_вых, мВ | K, дБ | +|---|---|---| +| | | | +| | | | + +Совмещённый график (расчёт / модель / эксперимент) ↓ + +``` +(место для графика) +``` + +--- + +## 6. Сводная таблица (задание 5) + +| Параметр | Расчёт | Симуляция | Железо | +|---|---|---|---| +| K | | | | +| τ, мс | | | | +| f_c, Гц | | | | + +**Причины расхождений:** + +1. Расчёт vs симуляция: ______________________________ +2. Симуляция vs железо: ______________________________ +3. Роль Monte Carlo: ______________________________ + +--- + +## 7. Выводы + +- +- +- + +--- + +## 8. Ответы на контрольные вопросы + +1. +2. +3. diff --git a/task.md b/task.md new file mode 100644 index 0000000..e18dbaf --- /dev/null +++ b/task.md @@ -0,0 +1,236 @@ +# Лабораторная работа + +## Интегратор и дифференциатор на ОУ: передаточная функция, АЧХ/ФЧХ и разброс по допускам + +**Дисциплина:** Электронные устройства мехатронных и робототехнических +систем (Б1.В.06, очная форма) +**Семестр:** 5 · **Объём:** 4 часа · **Тема:** `lab5-peredatochnaya-funkciya-na-ou` +**Форма:** черновик — в учебный план пока не привязана + +> AI-сгенерировано (2026-10-26), требует проверки преподавателем. + +--- + +## 1. Легенда + +В мехатронном модуле сигнал датчика проходит через аналоговую обработку: +фильтрацию, интегрирование, выделение скорости (дифференцирование). +Каждое такое звено описывается передаточной функцией, и от его параметров +(K, τ) зависит поведение всей системы управления. + +**Задача работы:** убедиться, что аналоговое звено на операционном +усилителе действительно реализует расчётную передаточную функцию — сначала +в симуляторе, затем на макетной плате. И понять, как **допуски** +резисторов и конденсаторов влияют на параметры звена в серии. + +Работа состоит из двух частей: + +- **Симуляция** (LTSpice): АЧХ/ФЧХ и **новый анализ — Monte Carlo** по допускам; +- **Железо** (макет + генератор): переходные процессы и **автоматическое + снятие АЧХ** генератором-свипом на RP2040. + +--- + +## 2. Теория кратко + +**Интегратор на ОУ** (R1 на входе, C1 в ООС): + +W(s) = −1 / (R1·C1·s) + +**Реальный интегратор** (резистор утечки R2 параллельно C1) — это +**апериодическое звено первого порядка**: + +W(s) = −R2 / (R1 · (1 + R2·C1·s)) = −K / (τ·s + 1) + +где K = R2/R1, τ = R2·C1, f_c = 1/(2π·τ). + +**Дифференциатор** (C1 на входе, R1 в ООС): + +W(s) = −R1·C1·s + +**Модель для работы:** K = −10, τ = 10 мс, f_c ≈ 16 Гц +(R1 = 10 кОм, R2 = 100 кОм, C1 = 0,1 мкФ). + +--- + +## 3. Задания + +### Задание 1 (1 ч). Симуляция: АЧХ и ФЧХ + +В LTSpice собрать интегратор с резистором утечки: R1 = 10 кОм, +R2 = 100 кОм, C1 = 0,1 мкФ (R2 || C1 в ООС). + +1. Задать анализ `.ac dec 20 1 100k`. +2. Снять АЧХ в децибелах и ФЧХ. +3. По графику определить: + - усиление на плоском участке (должно быть ≈ 20 дБ, т. е. K = 10); + - частоту сопряжения f_c (где спад −3 дБ); + - наклон спада (ожидается −20 дБ/дек). +4. Сравнить с расчётом по формулам из п. 2. + +### Задание 2 (1 ч). Симуляция: Monte Carlo по допускам ⭐ + +**Новый анализ.** Реальные резисторы и конденсаторы имеют допуск ±5 % +(ряд E24 — не лучше). Оценим разброс параметров звена. + +1. Задать разброс: `.step param tol list -5 -2.5 0 2.5 5` и применить + его к номиналам (например `{100k*(1+tol/100)}` для R2, аналогично R1 и C1). + Либо, для полноценного статистического анализа, использовать + `.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). Прямоугольник (ШИМ) и синус (DDS) + логарифмический свип + + измерение амплитуды на ADC0. +- **`stub/02-izmerenie-achh.py`** — хост-скрипт: запускает свип по Serial, + собирает точки, строит АЧХ. + +Порядок: + +1. Прошить генератор, проверить команды `F`, `W S`, `M`, `A` в мониторе + порта. +2. **Собрать внешний ФНЧ** на выходе генератора (без него будет меандр, + а не синус): + + ``` + GP15 ──[R1 1к]──┬──[R2 1к]──┬──────► вход схемы + │ │ + [C1 47н] [C2 47н] + │ │ + GND GND + ``` + + Это пассивный ФНЧ 2-го порядка, f_c ≈ 3,4 кГц; он подавляет несущую + ШИМ 62,5 кГц примерно на 50 дБ. **Зарисовать фильтр в отчёт.** + +3. Выход фильтра → вход схемы; выход схемы → вход измерения (ADC0). + **Если сигнал превышает 3,3 В — только через делитель.** +4. Запустить: + ``` + python 02-izmerenie-achh.py --port /dev/ttyACM0 \ + --f0 10 --f1 100000 --n 25 --dwell 150 --uin 500 --out achh.csv --plot + ``` +5. Импортировать CSV, нанести точки на модельную кривую из задания 1. +6. Объяснить расхождения. + +> **Смещение:** при скважности 50 % среднее на выходе ШИМ = `Uпит/2` +> = 1,65 В, поэтому синус смещён относительно земли. Если это мешает +> измерению — поставьте разделительный `C = 1 мкФ` + `R = 47 кОм` +> на землю, либо уменьшите амплитуду командой `M`. + +> Свип-генератор — студенческая заготовка (черновик). Если на стенде +> есть серийный функциональный генератор с режимом свипа/логарифмической +> развёртки — можно использовать его, принцип тот же. + +### Задание 5 (СРС / отчёт). Сведение результатов + +Свести в одну таблицу «**расчёт / симуляция / железо**» параметры +K, τ, f_c. Построить совмещённый график АЧХ (три кривые). + +Сделать выводы: + +- причины расхождения расчёта и симуляции; +- причины расхождения симуляции и железа; +- что даёт анализ Monte Carlo для реального проектирования. + +--- + +## 4. Варианты + +| № | 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 дают одинаковую +f_c при разном K — удобно для сравнения вклада параметров.* + +--- + +## 5. Оформление и оценивание + +Отчёт содержит: + +1. Схему интегратора и дифференциатора (KiCad или от руки). +2. АЧХ и ФЧХ из LTSpice. +3. Гистограммы Monte Carlo (K и f_c) + доля годных. +4. Осциллограммы переходных процессов (пила, импульсы). +5. CSV-точки автоматического свипа + совмещённый график АЧХ. +6. Итоговую таблицу «расчёт / симуляция / железо». +7. Выводы. + +| Задание | Баллы | +|---------|-------| +| 1. Симуляция АЧХ/ФЧХ | 2,0 | +| 2. Monte Carlo | 2,5 | +| 3. Железо: переходные процессы | 2,0 | +| 4. Железо: автоснятие АЧХ | 2,0 | +| 5. Отчёт: сведение | 1,5 | +| **Итого** | **10** | + +Зачёт — при **6 и более** баллах. Расхождение с эталоном ±10 % +(допуски компонентов). + +--- + +## 6. Контрольные вопросы + +1. Чему равна передаточная функция идеального интегратора и почему без + резистора утечки она нереализуема на практике? +2. Как по АЧХ отличить идеальный интегратор от апериодического звена + первого порядка? +3. Почему частота сопряжения определяется R2·C1, а не R1·C1? +4. Как связаны наклон АЧХ в дБ/дек и порядок звена? +5. Какой компонент даёт наибольший вклад в разброс f_c при допуске ±5 % + и почему? +6. Как на форме переходного процесса сказывается конечная полоса + пропускания операционного усилителя? + +--- + +## 7. Литература + +1. Хоровиц П., Хилл У. Искусство схемотехники. 3-е изд. М.: Бином, 2014. + Гл. 4. +2. Титце У., Шенк К. Полупроводниковая схемотехника. 12-е изд. М.: ДМК + Пресс, 2008. Т. 1, гл. 11. +3. Бесекерский В.А., Попов Е.П. Теория систем автоматического + регулирования. М.: Наука, 2010. Гл. 2. +4. LTSpice XVII User Guide. Analog Devices. +5. LM358 / TL081 datasheet. Texas Instruments. +6. RP2040 Datasheet. Raspberry Pi Ltd.