From 6f8d9f74154928d6db64ec886652e486faa85fe9 Mon Sep 17 00:00:00 2001 From: mss Date: Wed, 28 Oct 2026 21:53:49 +0400 Subject: [PATCH] =?UTF-8?q?ai:=20=D0=B2=D0=B0=D1=80=D0=B8=D0=B0=D0=BD?= =?UTF-8?q?=D1=82=205=20=D0=B3=D0=B5=D0=BD=D0=B5=D1=80=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=20=D0=BD=D0=B0=20audiopwmio=20(CircuitPython),=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B8=20=D0=B1?= =?UTF-8?q?=D1=80=D0=BE=D1=88=D1=8E=D1=80=D1=8B=20=D1=81=D0=B8=D0=BD=D1=85?= =?UTF-8?q?=D1=80=D0=BE=D0=BD=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=81=20=D0=A0=D0=9F=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...peredatochnaya-funkciya-na-ou-student.docx | Bin 47408 -> 47746 bytes ...peredatochnaya-funkciya-na-ou-teacher.docx | Bin 0 -> 53500 bytes stub/05-dds-audiopwm-rp2040.py | 854 ++++++++++++++++++ task.md | 6 + 4 files changed, 860 insertions(+) create mode 100644 print/methodical-lab5-peredatochnaya-funkciya-na-ou-teacher.docx create mode 100644 stub/05-dds-audiopwm-rp2040.py diff --git a/print/methodical-lab5-peredatochnaya-funkciya-na-ou-student.docx b/print/methodical-lab5-peredatochnaya-funkciya-na-ou-student.docx index f5ff278a942b63fadbd35ee0ff7534190a44d530..e9d5c72dc77307bb55a13540f2b4fa6879f0495f 100644 GIT binary patch delta 12358 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 Mg9Zw|^*`DF1D5`N_y7O^ delta 11996 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 z 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 diff --git a/print/methodical-lab5-peredatochnaya-funkciya-na-ou-teacher.docx b/print/methodical-lab5-peredatochnaya-funkciya-na-ou-teacher.docx new file mode 100644 index 0000000000000000000000000000000000000000..1272e9559b20fffb96327d0c28584b469023d349 GIT binary patch literal 53500 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 literal 0 HcmV?d00001 diff --git a/stub/05-dds-audiopwm-rp2040.py b/stub/05-dds-audiopwm-rp2040.py new file mode 100644 index 0000000..9d5aed5 --- /dev/null +++ b/stub/05-dds-audiopwm-rp2040.py @@ -0,0 +1,854 @@ +# DDS-генератор на аудио-ШИМ (RP2040) — CircuitPython +# +# Вариант 5 генератора для лабораторных работ. Совместим по системе команд +# с вариантами 1–4 (F, SF, W, D, M, A, SWEEP, STOP, B, O, N, FN, FP, I, +# CAL, HELP), но выход сделан не через PIO и не через программный ШИМ, +# а через штатный звуковой модуль CircuitPython audiopwmio. +# +# ЧЕРНОВИК (AI-сгенерировано, 2026-10-28). Требует проверки преподавателем +# на реальном стенде: частоты и разрядность посчитаны по исходникам ядра, +# но реальный размах и уровень несущей надо проверить осциллографом. +# +# Дополнительные библиотеки НЕ нужны: audiopwmio и audiocore входят в +# прошивку CircuitPython для RP2040. +# +# ──────────────── ПОЧЕМУ НЕ analogio (важно) ──────────────── +# +# В CircuitPython модуль analogio содержит ровно два класса: +# +# analogio.AnalogIn — вход АЦП (им и меряем, см. команду A); +# analogio.AnalogOut — выход ЦАП. +# +# AnalogOut работает только там, где есть НАСТОЯЩИЙ ЦАП. У RP2040 его нет, +# поэтому в документации прямо написано: «Not available on Nordic, RP2040, +# Spresense, as there is no on-chip DAC». То есть аналогового выхода на +# Pico через analogio не получить — ни в каком виде. +# +# Вывод «звука через ШИМ» в CircuitPython делает другой модуль — audiopwmio: +# +# audiopwmio.PWMAudioOut(pin) — канал вывода (ШИМ-слайс); +# audiocore.RawSample(буфер, ...) — проигрываемый сэмпл. +# +# Именно его и использует этот вариант. +# +# ──────────────── КАК ЭТО РАБОТАЕТ ──────────────── +# +# На RP2040 внутри audiopwmio: +# +# * занимается один ШИМ-слайс (GP15 — это слайс 7, канал B); +# * TOP регистра скважности = 1023, поэтому несущая ШИМ: +# +# f_несущей = 125 МГц / 1024 = 122,07 кГц (фиксирована ядром) +# +# * скважность (10 бит из 16-битного сэмпла) обновляется НЕ программой, +# а DMA по таймеру темпа. Таймер настраивается дробным делителем +# 125 МГц * X / Y, поэтому частота сэмплирования задаётся очень точно: +# +# sample_rate = f_вых * m, где m = N * O — сэмплов на период +# +# * после RC-фильтра низких частот остаётся среднее значение скважности, +# то есть наш сигнал. Несущие 122 кГц фильтр давит, сигнал пропускает. +# +# Отличие от варианта 1 и 2 (программный ШИМ) — в том, что цикл Python в +# формировании сигнала НЕ участвует вообще. Отличие от вариантов 3 и 4 +# (PIO) — в том, что вместо PIO-машины работает штатный аудио-тракт ядра. +# +# ──────────────── ЧТО ЭТО ДАЁТ И ЧЕГО НЕ ДАЁТ ──────────────── +# +# Плюсы: +# * вывод идёт в фоне (DMA), CPU свободен — команды принимаются на ходу, +# АЦП можно читать ОДНОВРЕМЕННО с выводом сигнала; +# * несущая 122 кГц фильтруется тем же RC, что и в остальных вариантах +# (1к/47н, f_c ~ 3,4 кГц); +# * не нужны adafruit_pioasm и rp2pio — только прошивка. +# +# Минусы (важно для лаборатории): +# * это ЗВУКОВОЙ тракт: частота сэмплирования ограничена сверху ~48 кГц, +# потому что она должна быть заметно ниже несущей 122 кГц. Значит +# верхняя частота сигнала: +# +# f_вых_max = sample_rate_max / m +# +# при m = 16 это 3 кГц, при m = 48 — 1 кГц, при m = 256 — 188 Гц. +# Выше 3–4 кГц этот вариант не годится, там нужны PIO (варианты 3–4) +# или программный ШИМ (варианты 1–2). +# * разрядность скважности 10 бит — команда B больше 10 не имеет смысла +# (ядро всё равно оставит 10 старших бит). +# * при малом m форма ступенчатая: 16 точек на период — это грубо. +# +# ──────────────── ПИНЫ ──────────────── +# +# GP15 — выход (ШИМ в режиме Q, аудио-ШИМ в режиме S); +# GP16 — синхроимпульс (вне зоны, которую занимает аудио); +# GP26 — вход ADC0 (A0), до 3,3 В, больше — только через делитель. +# +# ──────────────── КОМАНДЫ ──────────────── +# +# F <Гц> — частота (1..200000, но см. предел выше) +# SF <Гц> — то же, явно для синуса +# W Q | W S — режим: Q — прямоугольник (pwmio), S — звук (audiopwmio) +# D <0..255> — скважность прямоугольника в режиме Q +# M <0..127> — амплитуда (127 = полная шкала) +# A — измерить размах на ADC0 -> "A <мВ>" +# SWEEP f0 f1 n ms — свип: "P <Гц> <мВ>" на точку, затем "DONE" +# STOP — прервать свип +# B <1..10> — разрядность скважности (10 — предел audiopwmio) +# O <1..64> — множитель сэмплов: m = N*O +# N <16..4096> — «полезных» сэмплов на период +# FN <имя> — форма: sin, sine2, triangle, saw, square +# FP <выражение> — своя функция от t (0..1) +# CAL <Гц> — автокалибровка по осциллографу (поправка частоты) +# CLC — НЕ ПРИМЕНИМА (нет PIO); принимается для совместимости +# I — настройки, пределы частоты, фактическая частота +# +# ВНИМАНИЕ: ADC0 (GP26) — вход 0..3,3 В. Сигнал больше 3,3 В подавать +# только через делитель. Схему без питания к ADC не подключать. + +import array +import math +import sys +import time + +import board +import digitalio +import pwmio + +import audiocore +import audiopwmio + +try: + import analogbufio +except ImportError: # pragma: no cover + analogbufio = None + print("# analogbufio недоступен: команды A и SWEEP работают по-простому") + + +# ─────────────────────────── константы ─────────────────────────── + +PIN_OUT = board.GP15 # выход: PWM в режиме Q, аудио-ШИМ в режиме S +PIN_TRIG = board.GP16 # синхроимпульс +PIN_ADC = board.GP26 # ADC0 — вход измерения + +SYS_CLK = 125_000_000 # тактовая RP2040, Гц + +# Внутри audiopwmio на RP2040: BITS_PER_SAMPLE = 10, TOP = 2^10 - 1 = 1023. +# Отсюда фиксированная несущая ШИМ и предельная разрядность 10 бит. +PWM_BITS = 10 +PWM_CARRIER_HZ = SYS_CLK / (1 << PWM_BITS) # 122 070,3 Гц + +# Темп сэмплирования задаёт DMA-таймер с делителем до 65536, значит снизу +# частота ограничена ~1907 Гц (та же цифра, что предел clkdiv у PIO). +SR_MIN = SYS_CLK / 65536 # ≈ 1907 Гц +# Сверху ограничиваем «по-звуковому»: сэмплы должны быть заметно реже +# несущей, иначе ШИМ не успевает их отыграть и на выходе будет мусор. +SR_MAX = 48000 + +ADC_FULL_MV = 3300 # опорное напряжение ADC, мВ + +# Буфер сэмплов: 2 байта на сэмпл ("H"), держим не больше 64 КБ. +MAX_BUFFER_BYTES = 64 * 1024 + +# Пределы для команд N и O (те же, что в вариантах 3–4, для совместимости). +N_MIN, N_MAX = 16, 4096 +O_MIN, O_MAX = 1, 64 + + +def _default_wave(t): + """Форма по умолчанию: синус. t — доля периода [0,1).""" + return math.sin(2.0 * math.pi * t) + + +# ─────────────────────────── класс AudioPWMDDS ─────────────────────────── + +class AudioPWMDDS: + """DDS на audiopwmio: буфер сэмплов играет DMA, CPU свободен.""" + + def __init__(self, bits=8, oversample=1, n=32, freq=1000, level=127): + self.bits = int(bits) + self.oversample = int(oversample) + self.n = int(n) + self.freq = int(freq) + self.level = int(level) + self.wave = _default_wave + self.wave_name = "sin" + self.corr = 1.0 # поправка частоты после CAL + self.audio = None # создаётся лениво, в ensure() + self._sample = None # RawSample — держим ссылку! + self._buf = None # array('H') — буфер должен жить + + # ─── параметры ─── + + def samples_per_period(self): + """m — сколько сэмплов приходится на один период сигнала.""" + return self.n * self.oversample + + def sample_rate_wanted(self): + """Желаемая частота сэмплирования, Гц (до ограничения).""" + return self.freq * self.samples_per_period() * self.corr + + def sample_rate_used(self): + """Частота сэмплирования, которая реально будет выставлена.""" + sr = int(round(self.sample_rate_wanted())) + if sr < int(SR_MIN) + 1: + sr = int(SR_MIN) + 1 + if sr > SR_MAX: + sr = SR_MAX + return sr + + def f_out_actual(self): + """Фактическая частота сигнала при текущем sample_rate.""" + return self.sample_rate_used() / float(self.samples_per_period()) + + def f_out_max(self): + return SR_MAX / float(self.samples_per_period()) + + def f_out_min(self): + return (int(SR_MIN) + 1) / float(self.samples_per_period()) + + def needs_warning(self): + """True, если запрошенная частота не влезает в звуковой тракт.""" + sr = self.sample_rate_wanted() + return sr > SR_MAX or sr < SR_MIN + + def suggest_reduction(self): + """Подсказка, что менять, если частота не достижима.""" + m = self.samples_per_period() + if self.sample_rate_wanted() > SR_MAX: + ok = int(SR_MAX / float(self.freq * self.corr)) if self.freq else 0 + return ("уменьшите N*O до %d (сейчас m=%d) или снизьте частоту " + "до %.1f Гц" % (max(N_MIN, ok), m, self.f_out_max())) + return ("увеличьте N*O (сейчас m=%d): минимум %.1f Гц" + % (m, self.f_out_min())) + + def set_frequency(self, hz): + self.freq = max(1, min(200000, int(hz))) + if self.audio is not None: + self._reload() + + def set_bits(self, b): + b = int(b) + if b < 1: + raise ValueError("B должно быть 1..%d" % PWM_BITS) + if b > PWM_BITS: + raise ValueError("для audiopwmio максимум B=%d (ядро оставляет " + "10 старших бит)" % PWM_BITS) + self.bits = b + if self.audio is not None: + self._reload() + + def set_oversample(self, o): + o = int(o) + if o < O_MIN or o > O_MAX: + raise ValueError("O должно быть %d..%d" % (O_MIN, O_MAX)) + self._check_buffer(self.n * o) # проверить ДО присваивания + self.oversample = o + if self.audio is not None: + self._reload() + + def set_n(self, n): + n = int(n) + if n < N_MIN or n > N_MAX: + raise ValueError("N должно быть %d..%d" % (N_MIN, N_MAX)) + self._check_buffer(n * self.oversample) + self.n = n + if self.audio is not None: + self._reload() + + def set_amplitude(self, level): + self.level = max(0, min(127, int(level))) + if self.audio is not None: + self._reload() + + def set_function(self, fn, name="func"): + self.wave = fn + self.wave_name = name + if self.audio is not None: + self._reload() + + def reset_function(self): + self.set_function(_default_wave, "sin") + + def slew_warning(self): + """В этом варианте нет дельта-сигмы, поэтому ограничения наклона нет. + Метод оставлен для совместимости с вызовами из main().""" + return None + + # ─── буфер и воспроизведение ─── + + def _check_buffer(self, m=None): + """Проверить, что буфер для m сэмплов влезает в память.""" + if m is None: + m = self.samples_per_period() + if m * 2 > MAX_BUFFER_BYTES: + raise ValueError("буфер %d байт > %d — уменьшите N или O" + % (m * 2, MAX_BUFFER_BYTES)) + + def _build(self): + """Заполнить буфер: m сэмплов одного периода, 16 бит, 0..65535. + + Квантование по B бит делается ЗДЕСЬ, а не в железе: уровень + округляется до 2^B значений скважности и растягивается на всю + 16-битную шкалу. Так команда B честно показывает, сколько + ступенек увидит осциллограф. + """ + m = self.samples_per_period() + self._check_buffer(m) + + levels = (1 << self.bits) - 1 # 1, 3, 7, ... 1023 + amp = self.level / 127.0 + + buf = array.array("H", [0]) * m + for i in range(m): + u = self.wave(i / float(m)) * amp + if u > 1.0: + u = 1.0 + elif u < -1.0: + u = -1.0 + # 0.5 + 0.5*u -> 0..1; округляем до B-битной ступеньки + level = int(round((0.5 + 0.5 * u) * levels)) + buf[i] = level * 65535 // levels + self._buf = buf + return m + + def _reload(self): + """Пересобрать буфер и перезапустить воспроизведение.""" + self._build() + sr = self.sample_rate_used() + self._sample = audiocore.RawSample(self._buf, + channel_count=1, + sample_rate=sr) + if self.audio is not None: + self.audio.play(self._sample, loop=True) + + def ensure(self): + """Создать канал вывода и запустить сигнал (лениво).""" + if self.audio is None: + self.audio = audiopwmio.PWMAudioOut(PIN_OUT, + quiescent_value=0x8000) + self._reload() + return self + + def release(self): + """Остановить и освободить ШИМ-слайс (нужно для режима Q).""" + if self.audio is not None: + try: + self.audio.stop() + except Exception: + pass + try: + self.audio.deinit() + except Exception: + pass + self.audio = None + self._sample = None + self._buf = None + + def deinit(self): + self.release() + + def calibrate(self, measured_hz): + """CAL <измеренная_Гц>: подстроить частоту сэмплирования. + + Ошибка тут может быть только от кварца (доли промилле), но команда + оставлена для единообразия с вариантами 3–4: вводим измеренное, + получаем поправку corr и пересчёт. + """ + if self.needs_warning(): + raise ValueError("сначала задайте достижимую частоту: сейчас " + "запрошено %d Гц при пределе %.1f Гц" + % (self.freq, self.f_out_max())) + measured = float(measured_hz) + if measured <= 0: + raise ValueError("измеренная частота должна быть > 0") + old = self.corr + self.corr = self.corr * self.freq / measured + self.corr = max(0.5, min(2.0, self.corr)) + if self.audio is not None: + self._reload() + return old, self.corr + + def info(self): + m = self.samples_per_period() + return ("аудио-ШИМ: f=%d Гц, форма=%s, B=%d, N=%d, O=%d, m=%d, " + "Fs=%d Гц, несущая=%.1f кГц, f_ном=%.2f Гц, " + "поправка=%.6f, f_min=%.1f, f_max=%.1f Гц" + % (self.freq, self.wave_name, self.bits, self.n, + self.oversample, m, self.sample_rate_used(), + PWM_CARRIER_HZ / 1000.0, self.f_out_actual(), self.corr, + self.f_out_min(), self.f_out_max())) + + +# ───────────────────── прямоугольник на PWM ───────────────────── +# +# Режим Q — обычный аппаратный ШИМ на том же GP15. Одновременно с +# аудио-ШИМ он работать не может: audiopwmio занимает весь слайс. +# Поэтому режимы включаются по очереди (ensure/release), как в варианте 3. + +class SquarePWM: + def __init__(self, pin=PIN_OUT): + self.pwm = pwmio.PWMOut(pin, frequency=1000, + duty_cycle=0, variable_frequency=True) + + def set_frequency(self, f): + self.pwm.frequency = max(1, min(200000, int(f))) + + def set_duty(self, d): + d = max(0, min(255, int(d))) + self.pwm.duty_cycle = d * 65535 // 255 + + def off(self): + self.pwm.duty_cycle = 0 + + def deinit(self): + try: + self.pwm.deinit() + except Exception: + pass + + +# ─────────────────────────── АЦП ─────────────────────────── + +def measure_amplitude_mv(window_ms=50, rate=100000): + """Размах (пик-пик) на ADC0 в милливольтах. + + Чтение через analogbufio (аппаратный ADC + DMA). Если библиотеки нет + или DMA занят звуком — откатываемся на analogio.AnalogIn. + + ВАЖНО: воспроизведение при этом не останавливается — audiopwmio играет + на своём DMA-канале, ADC работает независимо. + """ + if analogbufio is not None: + length = int(rate * window_ms / 1000) + length = max(64, min(8192, length)) + buf = array.array("H", [0]) * length + adc = None + try: + adc = analogbufio.BufferedIn(PIN_ADC, sample_rate=rate) + adc.readinto(buf, loop=False) + return (max(buf) - min(buf)) * ADC_FULL_MV // 65535 + except Exception: + pass # нет DMA-канала или частоты — ниже + finally: + if adc is not None: + try: + adc.deinit() + except Exception: + pass + + import analogio + adc = analogio.AnalogIn(PIN_ADC) + vmin, vmax = 65535, 0 + t0 = time.monotonic() + try: + while (time.monotonic() - t0) * 1000 < window_ms: + v = adc.value + if v < vmin: + vmin = v + if v > vmax: + vmax = v + finally: + adc.deinit() + return (vmax - vmin) * ADC_FULL_MV // 65535 + + +# ─────────────────────────── свип ─────────────────────────── + +trig = None + + +def ensure_trig(): + """Создать синхроимпульс при первом использовании (лениво!).""" + global trig + if trig is None: + trig = digitalio.DigitalInOut(PIN_TRIG) + trig.direction = digitalio.Direction.OUTPUT + trig.value = False + return trig + + +def trigger_pulse(): + t = ensure_trig() + t.value = True + time.sleep(0.00005) + t.value = False + + +def run_sweep(dds, square, mode, f0, f1, count, dwell_ms): + """Логарифмический свип. Печатает 'P <Гц> <мВ>', в конце 'DONE'.""" + count = max(2, count) + if f1 <= f0: + f1 = f0 * 10.0 + ratio = (f1 / f0) ** (1.0 / (count - 1)) + f = float(f0) + try: + for _ in range(count): + if mode == "S": + dds.set_frequency(int(f)) + else: + square.set_frequency(int(f)) + trigger_pulse() + time.sleep(dwell_ms / 1000.0) + mv = measure_amplitude_mv() + sys.stdout.write("P %d %d\n" % (int(f), mv)) + f *= ratio + except KeyboardInterrupt: + sys.stdout.write("DONE\n") + raise + sys.stdout.write("DONE\n") + + +# ───────── предустановленные формы сигнала (для команды FN) ───────── + +def _wave_sin(t): + return math.sin(2.0 * math.pi * t) + + +def _wave_sine2(t): + return (0.3 * math.sin(2.0 * math.pi * t) + + 0.5 * math.sin(4.0 * math.pi * t)) + + +def _wave_triangle(t): + return 4.0 * abs(t - 0.5) - 1.0 + + +def _wave_saw(t): + return 2.0 * t - 1.0 + + +def _wave_square(t): + return 1.0 if t < 0.5 else -1.0 + + +WAVES = { + "sin": _wave_sin, + "sine2": _wave_sine2, + "triangle": _wave_triangle, + "saw": _wave_saw, + "square": _wave_square, +} + +# Разрешённые имена для команд FP/FN: только математика, без встроенных. +_EXPR_NAMES = { + "sin": math.sin, "cos": math.cos, "tan": math.tan, + "pi": math.pi, "abs": abs, +} + +EXPR_LEN_MAX = 120 + + +def _eval_expr(expr, t): + """Вычислить выражение от t. Отдельная функция, не lambda: на плате + разбор lambda в командах не срабатывал (см. вариант 3).""" + env = dict(_EXPR_NAMES) + env["t"] = t + return eval(expr, {"__builtins__": {}}, env) + + +def _expr_ok(expr): + """Проверить выражение до использования. None, если всё в порядке.""" + if len(expr) > EXPR_LEN_MAX: + return "выражение слишком длинное (лимит %d)" % EXPR_LEN_MAX + for t in (0.0, 0.125, 0.333, 0.5, 0.75): + try: + v = _eval_expr(expr, t) + except Exception as e: + return "%s (при t=%.3f)" % (e, t) + if v != v: # NaN + return "не числовой результат (NaN)" + if abs(v) > 1e6: + return "слишком большое значение (%g) — форма вне [-1,1]" % v + return None + + +def _make_expr_wave(expr): + def wave(t): + return _eval_expr(expr, t) + return wave + + +# ─────────────────────────── подробный хелп ─────────────────────────── + +def print_help(): + lines = [ + "# ─────── DDS-генератор на аудио-ШИМ (audiopwmio): команды ───────", + "# Обозначения: <..> — обязательный аргумент.", + "#", + "# РЕЖИМ И ЧАСТОТА", + "# W Q — режим прямоугольника (аппаратный ШИМ на GP15)", + "# W S — режим звука (audiopwmio, GP15)", + "# F <Гц> — частота, в режиме Q — прямоугольника,", + "# в S — сигнала. пример: F 440", + "# SF <Гц> — частота СИГНАЛА (то же, явно)", + "#", + "# ФОРМА СИГНАЛА", + "# D <0..255> — скважность прямоугольника (128 = 50 %)", + "# M <0..127> — амплитуда (127 = полная шкала)", + "# FN <имя> — форма: sin, sine2, triangle, saw, square", + "# FP <выражение> — своя функция от t (0..1), например:", + "# FP 0.3*sin(2*pi*t)+0.5*sin(4*pi*t)", + "#", + "# ИЗМЕРЕНИЕ И СВИП (работает ОДНОВРЕМЕННО с выводом)", + "# A — размах на ADC0 (GP26), мВ -> 'A <мВ>'", + "# SWEEP ", + "# логарифмический свип; печатает 'P <Гц> <мВ>',", + "# в конце 'DONE'. пример: SWEEP 20 3000 20 150", + "# STOP — прервать свип", + "#", + "# ПАРАМЕТРЫ СИНТЕЗА", + "# B <1..10> — разрядность скважности. 10 — предел ядра", + "# (внутри audiopwmio берутся 10 старших бит)", + "# O <1..64> — множитель сэмплов, m = N * O", + "# N <16..4096> — «полезных» сэмплов на период", + "# I — настройки, пределы, f_min/f_max, поправка", + "# CAL <Гц> — автокалибровка: подайте частоту, измерьте", + "# осциллографом, введите измеренное (CAL 440)", + "# CLC — НЕ ПРИМЕНИМА: PIO здесь нет; принимается", + "# только чтобы не ломать общий сценарий команд", + "#", + "# ГЛАВНОЕ ОГРАНИЧЕНИЕ (в чём отличие от вариантов 3–4)", + "# Частота сэмплирования не больше 48000 Гц, поэтому", + "# f_max = 48000 / m.", + "# При m=16 это 3 кГц, при m=48 — 1 кГц, при m=256 — 188 Гц.", + "# Выше 3–4 кГц этот вариант не работает — берите PIO.", + "# Команда I показывает f_min и f_max для текущих N и O.", + "#", + "# КАРТА ПИНОВ", + "# GP15 — выход (ШИМ в Q, аудио-ШИМ в S)", + "# GP16 — синхроимпульс", + "# GP26 (A0) — вход ADC, до 3,3 В (через делитель)", + "#", + "# ЧЕМ ЭТО ОТЛИЧАЕТСЯ ОТ analogio", + "# analogio умеет только AnalogIn (вход) и AnalogOut (ЦАП).", + "# На RP2040 ЦАПА НЕТ, поэтому AnalogOut недоступен, и «звук через", + "# ШИМ» делается модулем audiopwmio — он и используется здесь.", + "#", + "# ФИЛЬТР НА ВЫХОДЕ (тот же, что в остальных вариантах)", + "# GP15 --[R1]--+--[R2]--+--> во вход схемы", + "# | |", + "# [C1] [C2] R1=R2=1к, C1=C2=47н", + "# | | (f_c ~ 3.4 кГц)", + "# GND GND", + "# Несущая ШИМ 122 кГц давится этим фильтром примерно на 60 дБ.", + "#", + "# СПРАВКА", + "# HELP | ? — этот текст", + ] + for ln in lines: + sys.stdout.write(ln + "\n") + + +# ─────────────────────────── main ─────────────────────────── + +def main(): + print("# DDS на аудио-ШИМ (RP2040 / CircuitPython).") + print("# Вывод: audiopwmio, вход: analogio/analogbufio.") + print("# Подробный хелп: HELP или ?") + + dds = None + square = None + try: + dds = AudioPWMDDS(bits=8, oversample=1, n=32, freq=1000, level=127) + square = SquarePWM() + square.set_frequency(1000) + square.set_duty(128) + print("# " + dds.info()) + print(" (режим Q: PWM на GP15; режим S: audiopwmio на GP15)") + except Exception as e: + print("! ОШИБКА инициализации:", repr(e)) + if dds is not None: + dds.deinit() + if square is not None: + square.deinit() + return + + mode = "Q" + saved_square_hz = 1000 + + try: + while True: + line = sys.stdin.readline() + if not line: + break # EOF: порт закрыт + parts = line.split() + if not parts: + continue + cmd = parts[0].upper() + + if cmd in ("HELP", "?"): + print_help() + + elif cmd == "F" and len(parts) > 1: + hz = int(float(parts[1])) + if mode == "S": + dds.set_frequency(hz) + print("OK F %d (сигнал)" % dds.freq) + if dds.needs_warning(): + print("! ВНИМАНИЕ: частота недостижима — %s" + % dds.suggest_reduction()) + print("! Сейчас реально: %.1f Гц" % dds.f_out_actual()) + else: + square.set_frequency(hz) + print("OK F %d (прямоугольник)" % hz) + + elif cmd == "SF" and len(parts) > 1: + dds.set_frequency(int(float(parts[1]))) + print("OK SF %d" % dds.freq) + if dds.needs_warning(): + print("! ВНИМАНИЕ: частота недостижима — %s" + % dds.suggest_reduction()) + print("! Сейчас реально: %.1f Гц" % dds.f_out_actual()) + + elif cmd == "W" and len(parts) > 1: + want = "S" if parts[1].upper().startswith("S") else "Q" + if want == mode: + print("OK W %s (уже)" % mode) + else: + try: + if want == "S": + # запомнить частоту прямоугольника, погасить его, + # освободить слайс и запустить аудио-ШИМ + saved_square_hz = square.pwm.frequency + square.off() + square.deinit() + square = None + dds.ensure() + mode = "S" + print("OK W S (audiopwmio: %s)" % dds.info()) + else: + # остановить аудио, вернуть ШИМ на тот же GP15 + dds.release() + square = SquarePWM() + square.set_frequency(saved_square_hz) + square.set_duty(128) + mode = "Q" + print("OK W Q (PWM на GP15, %d Гц)" + % saved_square_hz) + except Exception as e: + print("ERR W %s:" % want, repr(e)) + + elif cmd == "D" and len(parts) > 1: + if mode == "Q" and square is not None: + square.set_duty(int(parts[1])) + print("OK D %s" % parts[1]) + + elif cmd == "M" and len(parts) > 1: + dds.set_amplitude(int(parts[1])) + print("OK M %d" % dds.level) + + elif cmd == "A": + print("A %d" % measure_amplitude_mv()) + + elif cmd == "SWEEP" and len(parts) > 4: + run_sweep(dds, square, mode, + float(parts[1]), float(parts[2]), + int(parts[3]), int(parts[4])) + + elif cmd == "STOP": + print("OK STOP (если свип идёт — надёжнее Ctrl-C)") + + elif cmd == "B" and len(parts) > 1: + try: + dds.set_bits(int(parts[1])) + print("OK B %d" % dds.bits) + except Exception as e: + print("ERR B:", repr(e)) + + elif cmd == "O" and len(parts) > 1: + try: + dds.set_oversample(int(parts[1])) + print("OK O %d" % dds.oversample) + except Exception as e: + print("ERR O:", repr(e)) + + elif cmd == "N" and len(parts) > 1: + try: + dds.set_n(int(parts[1])) + print("OK N %d" % dds.n) + except Exception as e: + print("ERR N:", repr(e)) + + elif cmd == "FN" and len(parts) > 1: + name = parts[1].lower() + if name in WAVES: + try: + dds.set_function(WAVES[name], name=name) + print("OK FN %s" % name) + except Exception as e: + print("ERR FN:", repr(e)) + else: + print("ERR FN: неизвестная форма. Доступны: %s" + % ", ".join(sorted(WAVES))) + + elif cmd == "FP" and len(parts) > 1: + expr = line.strip()[len("FP"):].strip() + if expr: + err = _expr_ok(expr) + if err: + print("ERR FP: %s" % err) + else: + try: + dds.set_function(_make_expr_wave(expr), + name="FP:" + expr) + print("OK FP %s" % expr) + except Exception as e: + print("ERR FP:", repr(e)) + dds.reset_function() + else: + print("ERR FP: укажите выражение, например " + "FP 0.3*sin(2*pi*t)+0.5*sin(4*pi*t)") + + elif cmd == "CLC" and len(parts) > 1: + # Команда есть в вариантах 3–4 (тактов PIO на сэмпл). + # Здесь PIO нет: частоту задаёт DMA-таймер, подстраивать + # нечего. Принимаем, чтобы общий сценарий не падал. + print("OK CLC %s (не применима: здесь нет PIO; для поправки " + "частоты — CAL)" % parts[1]) + + elif cmd == "CAL" and len(parts) > 1: + try: + was, now = dds.calibrate(float(parts[1])) + print("OK CAL: поправка %.6f -> %.6f (Fs=%d Гц, " + "физическая частота должна стать %d Гц)" + % (was, now, dds.sample_rate_used(), dds.freq)) + except Exception as e: + print("ERR CAL:", repr(e)) + + elif cmd == "I": + print("# " + dds.info()) + + else: + print("ERR unknown command: %s" % cmd) + + except KeyboardInterrupt: + pass + finally: + dds.deinit() + if square is not None: + square.deinit() + if trig is not None: + try: + trig.deinit() + except Exception: + pass + print("stopped") + + +# ─────────────── точка входа ─────────────── +# +# Как и в других вариантах, запускаем безусловно: в CircuitPython проверка +# `if __name__ == "__main__":` при автозапуске code.py ненадёжна. + +_START_GENERATOR = True + +if _START_GENERATOR: + try: + main() + except KeyboardInterrupt: + pass + except Exception as _e: + try: + import sys as _sys + _sys.print_exception(_e) + except Exception: + print("! ОШИБКА:", repr(_e)) diff --git a/task.md b/task.md index 7c64766..668024a 100644 --- a/task.md +++ b/task.md @@ -197,8 +197,14 @@ K(f) = 1 / √(1 + (f/f_c)²), f_c = 1/(2π·R·C) | `01-...-circuitpython.py` | CircuitPython | программный DDS + ШИМ | | `04-dds-pio-rp2040.py` | CircuitPython | аппаратный PIO + DMA | | `04-dds-pio-rp2040.ino` | Arduino, **только earlephilhower** | аппаратный PIO + DMA | +| `05-dds-audiopwm-rp2040.py` | CircuitPython | аудио-ШИМ (`audiopwmio`) + DMA; только до ~3 кГц | **Рекомендуется вариант на PIO** — точная частота, CPU свободен. +Вариант 3 (`04-dds-pio-rp2040.py`) проверен на стенде: логическим +анализатором снят цифровой выход, форма синуса верная. +Вариант 5 — если интересно, как звук выводят штатными средствами ядра +(`audiopwmio`); он ограничен сверху ~3 кГц, потому что частота +сэмплирования не может быть выше 48 кГц. У `.ino`-варианта на PIO форма сигнала задаётся функцией `waveform(t)` **в коде** (перекомпилировать после правки) — в C++ нет разбора формул на лету, как в CircuitPython-версии.