Как сделать синусоиду на ардуино

Обновлено: 05.07.2024

В данной статье рассказывается о том, как с помощью Arduino генерировать сигналы. Всё написанное также верно и для клонов Arduino, например Freeduino.

В статье встречаются технические термины, для понимания которых могут быть не бесполезны статьи Использование прерываний Arduino, Порты ввода-вывода Arduino и Как подключить к Arduino.

При подключении к Arduino динамика с регулятором громкости, в качестве микропрограммы использовался скетч toneMelody из меню Examples->Digital, проигрывающий мелодию после сброса или включения Arduino. Если посмотреть, как устроен код этого скетча, то выясняется, что ноты воспроизводятся с помощью функции tone() , которая схожа с функцией delay() тем, что пока выполняется функция, программа ждёт окончания её выполнения.

Но что, если я захочу например подключить к Arduino несколько кнопок и играть разные ноты, или подключить потенциометр и менять тональность звучащей ноты? Ведь нота должна звучать пока нажата кнопка, то есть мне нужна возможность и воспроизводить звук, и опрашивать порты ввода-вывода одновременно.

Такая возможность у микроконтроллера Arduino есть, но для это мне потребуется освоить прерывания и программирование таймеров.

Методы генерации сигналов с помощью таймеров отличаются в разных режимах таймеров.

В нормальном режиме таймер-счётчик последовательно увеличивает значение регистра TCNTn (где n - номер счётчика) на каждом такте генератора, от которого таймер-счётчик приводится в действие. Когда значение регистра TCNTn достигает максимального, то на следующем такте происходит переполнение счётчика, регистр обнуляется и вызывается прерывание по переполнению TIMERn_OVF_vect , если вызов этого прерывания включен.

Соответственно, метод генерирования сигналов в нормальном режиме применяется один из двух.

В первом случае разрешается переключение состояния вывода OCRnx (где x - это A или B ). Это удобно, поскольку не требует тратить на генерацию сигнала процессорного времени, но таким образом можно получить только ограниченное число частот - по количеству значений предделителя. То есть пять частот для таймеров 0 и 1, и 7 частот для таймера 2.

Тем не менее, второй способ более похож на программную реализацию режима CTC (очистки при совпадении), поэтому этот метод применяется в основном для использования ШИМ в качестве цифро-аналогового преобразователя.


Дело было вечером делать было нечего)
Итак, встречайте — генератор с частотомером на борту.


После успешного проекта по сборке пультоскопа решил собрать генератор и частотомер. Вот что из этого вышло:
Формы сигнала: синус DDS, треугольник DDS, прямоугольник DDS, правая пила DDS, левая пила DDS.
Характеристики взял с страницы автора
"генерации таймером:
Генерация прямоугольного сигнала 0.4 Мгц,
минимальный шаг регулировки частоты в диапазоне 0…2,8кГц — 1Гц
свыше 2,8кГц минимальный шаг постепенно возрастает.
Регулировка коэффициента заполнения (скважности) 1.100%
в диапазоне 1Гц.80кГц регулировка производится с разрешением 1%
Свыше 80кГц разрешение (шаг) регулировки скважности увеличивается.
При изменении рабочей частоты в диапазоне 1Гц-80кГц выбранная скважность сохраняется,
а при изменении частоты свыше 80кГц сбрасывается на 50 %,
но в режиме регулировки скважности её можно снова изменять.

Тех. Характеристики генерации сигнала через DDS:
Почему-то в оригинальной статье автора алгоритма DDS о характеристиках нет ни слова.
Указана только максимальная частота -65кГц. Откуда её взял автор непонятно, я поставил ограничение на 100кГц C увеличением частоты сильно падает разрешение получаемого сигнала на высоких частотах. А конкретно, в диапазонах:
0…6,25 кГц — разрядность от 256 до 128 градаций
6,25…12,5 кГц — разрядность от 128 до 64 градаций
12,5…25кГц -разрядность от 64 до 32 градаций
25кГц…50кГц -разрядность от 32 до 16 градаций
50кГц…100кГц -разрядность от 16 до 8 градаций
Помимо этого с увеличением частоты вырастает джиттер,
особенно заметно на сигналах с резкими фронтами (прямоугольник, пила).
Но на точно установленных частотах 6,25кГц ; 12,5кГц ; 25кГц; 50кГц; 100 кГц джиттера нет, их можно использовать для точных измерений. Остальные частоты для большинства применений тоже подойдут.
Но если нужен идеальный сигнал -то только генерация таймером."
Во всех диапазонах DDS минимальный шаг регулировки частоты — 1Гц.
Характеристики частотомера, измеряемая частота 1Гц … 7,999 МГц, при превышении частоты начинает привирать.
Есть еще входы на вольтметр, он встроен в меню, но я его не использовал.


За основу взял проект с сайта Ардуино.ру. Проект повторен и проверен несколькими комрадами. Я перевел меню на Русский язык, развел печатную плату и спаял)
В проекте используется Arduino Nano, LCD Nokia 5110 и энкондер "одношаговый".
Управление: кнопка переключения режимов переключает последовательно
синус DDS, треугольник DDS, прямоугольник DDS, правая пила DDS,
левая пила DDS. частота генерации таймером, скважность генерации таймером

Кнопка на энкодере переключает шаг изменения частоты 1000-1-10-100
в режиме регулировки скважности(6) нажатие на кнопку переключает энкодер в режим (5).
При старте есть возможность выбора режима, генератор-вольтметр. После обратного отсчета автоматом включается генератор.
Подсветка включается комбинацией — удерживая кнопку энкондера нажать кнопку режима послеотпустить кнопку энкондера.
Файлы проекта будут доступны по ссылке

Но есть проблемка форма выходного сигнала прямоугольной формы а не чистая синусоида. А для питания компьютера и водяного насоса нужна чистая синусоида. Как заставить Ардуино генерировать импульс чистой синусоиди частотой 50 Гц так штобы положительный полупериод формировался на одном Пине а отрицательный на другом Пине .. так как есть 2 плеча транзисторов для питания первичной обмотки трансформатора ..
вот нарыл скетч в интернете может поможет упростить задачу написания моего скетча. Не могу разобратся осциллограф ресует чистый синус но неразводит полупериода по 2м каналам и частота 1,3 мегагерца.

Задающий генератор на ОУ для Г3-36А
Вариант замены нестабильно работающего задающего генератора на основе моста Вина в ГЗЧ Г3-36А на.

Схема импульсного преобразователя 220В -> 5В
Пожалуйста, ткните носом в схему импульсного преобразователя, аля зарядка для смартфона.

3-х фазный генератор задающий на xMega
Добрый день/вечер/ночь) Хотелось бы спросить у глубоко знающих людей, у тех, кто давно пишет.

Arduino uno + arduino ethernet + delphi для чайников
Доброго времени суток. У меня такая задача нужно реализовать программу на Delphi которая.

КдПВ


Я недавно в форуме чисто теоретически поднимал вопрос о бесперебойнике с чистым синусом.

А тут еще стабилизатор сгорел, от которого котел газовый запитан был, да с такими спецэффектами сгорел, что до сих пор запах горелой изоляции в кухне. Слава Богу, УЗО отработало, проводка выдержала, в общем, обошлось.

Так что теория постепенно начала превращаться в практику, но пока (на уровне идеи) с использованием железного трансформатора от сгоревшего UPS, коих у меня накопилось уже много.

Использовать будем Timer1 микроконтроллера ATMega168. Подойдет и ATTiny2313, у него такой же таймер1.

Имеющийся у меня трансформатор (как и большинство дешевых UPS) имеет отвод от средней точки низковольтной обмотки. Поэтому нужно сделать генерацию раздельных полуволн с двух выходов сравнения таймера.

Для обеспечения диапазона подстройки частоты вниз, максимальное значение заполнения ШИМ не доходит до значения регистра ICR1. Запас я взял 10%, хотя, думаю, можно его и уменьшить.

Для облегчения задачи я сделал простую табличку расчета параметров таймера и таблицы синуса под нужные параметры. Кстати, ее легко адаптировать под другие задачи.

Таблицу синуса я использовал для простоты, но, пользуясь информацией из интернета, можно генерировать вполне приемлемый синус на лету. Я проверил, результат получается очень близкий. Или подготовить таблицу при старте контроллера. К сожалению, для достижения необходимой точности этот метод требует умножения чисел с несколькими цифрами после запятой или каких-то трюков, поэтому я пока от него отказался.

Таблица содержит только четверть периода синуса, остальное повторяется в разном порядке, ну, вы поняли.
Количество импульсов ШИМ на период синуса фиксированное, оно расчитывается из исходных данных в таблице.

Схема в протеусе выглядит так:


Сигнал на осциллографе протеуса:


Параметры трансформатора, конечно, с потолка, только для получения формы сигнала на выходе. Работает и просто с RC-цепочками на выходах МК.


Вот еще картинки:




Здесь синусоида отстает немного, так как фильтрацию сделал на индуктивностях.

Модель для протеуса цепляю к статье.

Комментарии ( 22 )

Я бы порекомендовал использовать, что нибудь на ARM (например STM32), в которых возможности таймеров значительно расширены.

Синус-то из таблицы можно один раз вычислять в начале обработчика, и значение положить во временную переменную. И оттуда брать, тогда не надо будет 4 раза индексы считать.

Индекс вообще считается автоматически, один раз за прерывание, а в зависимости от четверти меняется направление счета и выход, на который подается сигнал.

Про автоматически это интересно, конечно)) Но Вы листинг все же взгляните что там в начале каждого case. Не начинается ли каждый case с высчисление адреса по индексу массива? Возможно, узнаете много нового про компилятор. Удачи!

Автоматически имел в виду в прерывании, один раз. На каждом следующем прерывании новое значение. Что вы предлагаете, не понимаю?

Что ж там не понять? Откройте листинг с ассемблерными инструкциями. Посмотрите начало каждого case. Что там делается? Не вычисляется ли в КАЖДЫЙ раз по индексу адрес загружаемого данного? Видимо, вычисляется)) Это штук 7 ASM-инстукций, если не больше. От этого можно избавиться, если при входе в обработчик ОДИН раз взять из памяти значение и НЕ ВЫЧИСЛЯТЬ его адреса в каждом case.

Каждый раз при вызове прерывание отрабатывает одно из ветвлений case, и будет происходить одно обращение к таблице один раз на прерывание. Конечно, можно вынести чтение из массива перед case, но в данном случае ничего не изменится. Если вы переживаете за размер кода – оптимизатор сам вполне справляется с подобными вещами.

Меня больше смущает, что переменные


не объявлены как volatile (потенциально оптимизатор может поломать код)

Меня больше смущает, что переменные

не объявлены как volatile (потенциально оптимизатор может поломать код)

Ну, ИАР не делает одно обращение никогда. Он в лучшем случае (при макс. оптимизации) в начале каждого case сделает call на общую подпрограмму извлечения слова из массива. А это — лишние такты внутри обработчика. Некультурно))

будет храниться в памяти RAM.
Нужно отчетливо понимать, что мы имеем дело с гарвардской архитектурой. Это значит, что область ОЗУ и область программ имеют свою адресацию. Поскольку компилятор не обладает искусственным интеллектом, ему требуется подсказать, что читать нужно из другой области памяти.
нужно использовать функции чтения из памяти pgmspace.h
а вначале ставить макрос PROGMEM.
Здесь на этом же сайте уже писалось об этом. Почитайте.

переменная
const uint16_t sinus[PULSE_PER_QUADRANT]

будет храниться в памяти RAM

по схеме: Конечно, одно из самых больших преимуществ данной схемы — простота, однако есть серьезный недостаток: Транзисторы будут сильно греться, причем не в прямом, а в обратном режиме при протекании тока через защитный диод. Так как на диодах есть сравнительное большое падение напряжения, выделяемая мощность будет произведением тока и этого напряжения. Решайте сами.

Поясню: это только иллюстрация идеи, не дальше чем моделирование.

В прототипе будут другой контроллер, другие драйверы, другие транзисторы, другие резисторы, защитные диоды, обратные диоды в затворе, блокировочные конденсаторы, накопительные конденсаторы, предохранители, другой трансформатор, провода потолще :-)))…

значит соответственно и другая программа. А что мы обсуждаем тогда вообще? Сама идея синуса на МК тоже не нова.

Программа будет дополняться другими функциями: синхронизация с сетью, раннее определение отключения сети, синхронное переключение на симисторах, стабилизация напряжения на выходе, контроль параметров аккумулятора, индикация режимов.

Для меня новое в этой программе — возможность подстройки частоты в определенных пределах без изменения количества отсчетов за период. К слову, не все таймеры на AVR имеют такую возможность, например, ATTiny85, который я сначала хотел использовать, не имеет регистра ICR.

А честный синус сейчас мало где нужен вообще.
Например, если БП сделан по схеме Диодный мост->конденсатор->ШИМ, то ему меандр (е ащё лучше — постоянка) — самое то.
Чистый синус нужен для повышения КПД низкочастотных трансформаторов и двигателей. Однако, низкочастотные трансформаторы это странно, а двигатели надо пускать через частотники, а там

Читайте также: