воскресенье, 24 июня 2018 г.

Генератор сигналов на AD9833

Генератор AD9833
AD9833 - это программируемый генератор сигналов с низким энергопотреблением. Позволяет генерировать сигналы с частотой до 12.5МГц синусоидальной, треугольной и прямоугольной формы. Программирование осуществляется с использованием трехпроводного интерфейса SPI и не составляет труда. Ниже приведены основные характеристики микросхемы:

  • Цифровое программирование частоты и фазы.
  • Потребляемая мощность 12.65 мВт при напряжении 3 В.
  • Диапазон выходных частот от 0 МГц до 12.5 МГц.
  • Разрешение 28 бит (0.1 Гц при частоте опорного сигнала 25 МГц).
  • Синусоидальные, треугольные и прямоугольные выходные колебания.
  • Напряжение питания от 2.3 В до 5.5 В.
  • Трехпроводной интерфейс SPI.
  • Расширенный температурный диапазон: от –40°C до +105°C.
  • Опция пониженного энергопотребления.

Более подробную информацию вы можете найти в даташите. В характеристиках также заявлено, что микросхема не требует внешних компонентов, но здесь производитель лукавит: обвязка и источник опорной частоты все же нужны. На Али продаются модули AD9833 с необходимой обвязкой и кварцевым генератором на 25 МГц, как раз с таким модулем я и собираюсь экспериментировать. Данный модуль имеет следующие выводы:

  • VCC – плюс питания для цифровых и аналоговых цепей генератора.
  • DGND – цифровая земля.
  • SDATA – вход данных интерфейса SPI. Передача осуществляется 16-битными словами.
  • SCLK – вход тактового сигнала SPI. Используется второй режим работы: (CPOL = 1, CPHA = 0).
  • FSYNC – выбор микросхемы. Перед началом передачи данных должен быть установлен в 0, по завершении в 1.
  • AGND – аналоговая земля.
  • OUT – выход генератора.
Попробуем подключить этот модуль к Ардуино и научиться им управлять. Для начала ознакомимся с его функциональной схемой:

Функциональная схема AD9833

AD9833 состоит из следующих основных частей: два регистра выбора частоты, аккумулятор фазы, два регистра выбора фазы и сумматор смещения фазы (вместе эти компоненты составляют генератор с цифровым управлением - NCO), SIN ROM для преобразования информации о фазе в амплитуду и 10-разрядный цифро-аналоговый преобразователь.

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

Управляющий регистр

Это 16-разрядный регистр, управляющий работой генератора. Подробное описание его битов приведено ниже в таблице. Схема из даташита также наглядно демонстрирует их назначение:



Бит Название Назначение
15, 14 DB15, DB14 Чтобы AD9833 понял, что принятое по SPI 16-битное слово содержит новое значение для управляющего регистра, два старших бита в слове должны быть установлены в 0.
13 B28 Регистры частоты AD9833 имеют разрядность 28 бит, поэтому для изменения их содержимого требуется передача двух 16-битных слов. Однако в некоторых случаях требуется изменить только старшую или младшую часть регистра частоты. Здесь и используется данный признак: B28 = 1 говорит о том, что необходимо обновить регистр частоты целиком и его новое значение будет передано двумя последовательными записями. Первая запись содержит 14 младших бит, вторая 14 старших бит. Первые два бита в обеих записях определяют регистр частоты, в который будет записано передаваемое значение и должны быть одинаковыми. Обновление регистра частоты происходит после получения полного слова, поэтому запись промежуточного значения в регистр исключена. B28 = 0 позволяет обновить отдельно старшую или младшую часть регистра. Какая именно часть будет изменена определяется управляющим битом HLB.
12 HLB Бит HLB определяет, какая из частей регистра частоты (младшая или старшая) будет перезаписана. Используется при B28 = 0. При B28 = 1 значение этого бита игнорируется. HLB = 1 позволяет обновить старшие 14 бит регистра частоты; HLB = 0 позволяет обновить младшие 14 бит регистра частоты.
11 FSELECT Бит FSELECT определяет, какой из регистров используется в аккумуляторе фазы – FREQ0 или FREQ1.
10 PSELECT Бит PSELECT определяет, данные какого из регистров PHASE0 или PHASE1 добавляются к выходу аккумулятора фазы.
9 Зарезервирован Данный бит зарезервирован и должен быть установлен в 0.
8 RESET RESET = 1 сбрасывает внутренние регистры генератора в 0. Сброс не затрагивает регистры управления, частоты и фазы.
7 SLEEP1 При SLEEP1 = 1 запрещается внутреннее тактирование, приостанавливается работа NCO и выход генератора остается в своем текущем состоянии. При SLEEP1 = 0 тактирование разрешено.
6 SLEEP12 При SLEEP12 = 1 отключается внутренний ЦАП. Это может быть полезно для генерации прямоугольных импульсов, при которой не требуется выполнение цифро-аналоговых преобразований. При SLEEP12 = 0 внутренний ЦАП активен.
5 OPBITEN Данный бит вместе с битом MODE управляют выходом генератора. При OPBITEN = 1 внутренний ЦАП отключается от выхода VOUT и для генерации выходного сигнала используется значение старшего значащего бита с входа ЦАП, что позволяет получить на выходе генератора прямоугольные импульсы.
4 Зарезервирован Данный бит зарезервирован и должен быть установлен в 0.
3 DIV2 Используется в паре со значением OPBITEN = 1. При DIV2 = 1 значение старшего значащего бита данных с входа ЦАП подается напрямую на выход VOUT. DIV2 = 0 позволяет задействовать делитель частоты и уменьшить частоту выходного сигнала вдвое. При OPBITEN = 0 значение данного бита игнорируется.
2 Зарезервирован Данный бит зарезервирован и должен быть установлен в 0.
1 MODE Данный бит вместе с битом OPBITEN управляют выходом генератора. При OPBITEN = 1 бит MODE должен быть установлен в 0. Значение MODE = 0 позволяет получить на выходе генератора синусоидальный сигнал. При MODE = 1 на выходе будет треугольный сигнал.
0 Зарезервирован Данный бит зарезервирован и должен быть установлен в 0.

И для лучшего понимания назначения битов OPBITEN, MODE и DIV2 я приведу таблицу с их допустимыми комбинациями и формой результирующих сигналов на выходе:

OPBITEN MODE DIV2 Сигнал на выходе VOUT
0 0 X Синусоидальный
0 1 X Треугольный
1 0 0 Прямоугольный с частотой F/2
1 0 1 Прямоугольный с частотой F
1 1 X Зарезервировано

Регистры частоты и фазы

Генератор AD9833 имеет 2 регистра частоты и 2 регистра фазы разрядностью 28 бит и 12 бит соответственно. 

Выбор активного регистра частоты осуществляется установкой управляющего бита FSELECT: при FSELECT = 0 активным является FREQ0; при FSELECT = 1 активен регистр FREQ1. Результирующая частота на выходе генератора определяется следующим образом:

(FMCLK / 228) * FREQREG,

где FMCLK – это опорная частота, FREQREG – значение, загруженное в активный регистр частоты. Таким образом, если мы хотим получить на выходе генератора сигнал с частотой 400Гц при опорной частоте 25МГц, в активный регистр  должно быть загружено значение:

FREQREG = FOUT*228 / FMCLK = 400Гц * 228 / 25МГц ≈ 4295

Для того чтобы загрузить значение FREQREG в регистр частоты необходимо старшие биты передаваемого по SPI значения установить в 01 для загрузки в FREQ0 или 10 для загрузки в FREQ1. Напомню, что общение с AD9833 осуществляется по SPI 16-битными словами.

Фаза выходного сигнала определяется следующим образом:

(2π / 212) * PHASEREG

соответственно, значение для регистра фазы вычисляется по формуле:

PHASEREG = PHASE*212 / 2π

В приведенных формулах PHASEREG – это значение активного регистра фазы. Выбор активного регистра осуществляется установкой управляющего бита PSELECT: при PSELECT = 0 активным является PHASE0; при PSELECT = 1 активен регистр PHASE1.

При записи нового значения в регистр фазы старшие биты должны быть установлены в 11, а выбор регистра, в который должно быть записано значение, осуществляется установкой бита 13: при нулевом его значении будет обновлен регистр PHASE0; при установке указанного бита в 1 будет обновлен регистр PHASE1. 12й бит не используется, а биты с 0 по 11 содержат значение для регистра фазы.

Разрядность регистра частоты в 28 бит при опорной частоте 25МГц обеспечивает шаг 0.1Гц для установки частоты сигнала на выходе. А 12-битный регистр фазы обеспечивает разрешение 2π/4096.


Тестовая программа для AD9833 на Ардуино

Теперь мы можем написать первую программу для AD9833. Схема подключения модуля AD9833 к Ардуино и скетч приведены ниже.

Схема подключения AD9833 к Ардуино
С подключением все просто: общение с модулем происходит по интерфейсу SPI, для которого на Ардуино отведены следующие пины:

D10 - SS (Slave Select - выбор ведомого), к нему подключаем вывод FSYNC модуля.
D11 - MOSI (Master Out Slave In - выход ведущего, вход ведомого), к нему подключаем вывод SDATA.
D13 - SCK (Serial Clock - Тактовый сигнал), к нему подключаем вывод SCLK.

#include <SPI.h>

void setup() {
  SPI.begin();
  WriteAD9833(0x2100); //0010 0001 0000 0000 - Reset + DB28
  WriteAD9833(0x50C7); //0101 0000 1100 0111 - Freq0 LSB (4295)
  WriteAD9833(0x4000); //0100 0000 0000 0000 - Freq0 MSB (0)
  WriteAD9833(0xC000); //1100 0000 0000 0000 - Phase0 (0)
  WriteAD9833(0x2000); //0010 0000 0000 0000 - Exit Reset
}

void WriteAD9833(uint16_t Data){
  SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE2));
  digitalWrite(SS, LOW);
  delayMicroseconds(1);
  SPI.transfer16(Data);
  digitalWrite(SS, HIGH);
  SPI.endTransaction();
}

void loop() {
  WriteAD9833(0x2000); //0010 0000 0000 0000 - Синусоидальный сигнал
  delay(5000);
  WriteAD9833(0x2002); //0010 0000 0000 0010 - MODE=1 - Треугольный
  delay(5000);
  WriteAD9833(0x2020); //0010 0000 0010 0000 - OPBITEN=1 - Прямоугольный (MSB/2)
  delay(5000);
  WriteAD9833(0x2028); //0010 0000 0010 1000 - OPBITEN=1, DIV2=1 - Прямоугольный (MSB)
  delay(5000);
 }

В данном скетче выполняются следующие действия:
  • При первом вызове функции WriteAD9833 производится установка управляющего регистра: бит RESET устанавливается в 1 для выполнения сброса; бит DB28 устанавливается в 1 для перезаписи всего содержимого регистра частоты; биты FSELECT и PSELECT содержат 0, поэтому для генерации выходного сигнала будут использоваться регистры FREQ0 и PHASE0.
  • Следующие два вызова передают значение 4295 в регистр частоты FREQ0. Данное значение умещается в 14 младших разрядах, поэтому в старшие разряды регистра записываем нули.
  • Сдвиг по фазе не требуется - запишем в регистр PHASE0 значение 0
  • Последним вызовом WriteAD9833 в процедуре setup снимаем бит RESET, разрешая тем самым работу генератора. Результирующий сигнал поступает на вывод VOUT.
  • Следующие вызовы WriteAD9833 в функции loop обновляют содержимое управляющего регистра, перебирая комбинации битов MODE, OPBITEN и DIV2 для генерации сигнала синусоидальной, треугольной и прямоугольной форм.
Вот как выглядит выходной сигнал генератора в виртуальном осциллографе:

Синусоидальный сигнал (биты MODE и OPBITEN сброшены в 0)

Треугольный сигнал (MODE = 1, OPBITEN = 0)

Прямоугольный сигнал (OPBITEN = 1, MODE = 0, DIV2 = 1)

Прямоугольный сигнал (OPBITEN = 1, MODE = 0, DIV2 = 0)

Обратите внимание: при генерации синусоидальных и треугольных импульсов, когда сигнал снимается с выхода ЦАП, его амплитуда изменяется в диапазоне 38мВ...0,65В. При генерации импульсов прямоугольной формы мы имеем дело с обычным цифровым сигналом с соответствующими уровнями напряжения. Так в последних двух осциллограммах логической единице соответствует напряжение ~4,5В.

Генератор на AD9833 с дисплеем и энкодером

Разобравшись с управлением AD9833 можно приступать к созданию генератора с интерфейсом управления и индикацией. Для этого добавим в нашу схему энкодер вращения и жидкокристаллический дисплей:
Схема генератора на AD9833 с дисплеем и энкодером KY-040

Ранее я писал о том, как можно сделать меню на Ардуино с энкодером вращения. И сейчас я взял такое меню за основу скетча, добавив в него функционал для работы с AD9833. Скачать скетч можно по ссылке.

При включении питания AD9833 настраивается на генерацию синусоидального сигнала частотой 100Гц, соответствующая информация отображается на дисплее. Вращая ручку энкодера можно изменять его частоту, а при нажатии вызывается меню. В меню доступны следующие опции:

  • Установка частоты (можно задать произвольное значение от 1 до 12,5МГц).
  • Установка фазы (0 - 360°).
  • Выбор формы сигнала.
  • Выбор значения, на которое изменяется частота при вращении ручки энкодера.

Остается только поместить все компоненты в подходящий корпус и получится законченное устройство. Результат работы в следующем ролике:




221 комментарий:

  1. Подскажите по статье, есть пара вопросов:
    1. В описании библиотеки SPI сказано (насколько я понял), что SS пин и его состояние относится к самому ардуино и при установке низкого потенциала, интерфейс переходит в слейв режим. Вроде не должно работать.
    2. В описании микросхемы сказано, что SCK д.б. в единице, когда FSYNC опускается в ноль. Возможно тут имеется ввиду момент считывания значения. После этого немедленно начинается чтение переданных данных. У Вас между этими событиями присутствует задержка на 1мкс, которая должна вносить искажение в передачу.
    Сам мучаю подобный модуль, он ни в какую не хочет у меня работать.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      1. SPI не переключится в режим slave, пока SS пин настроен как OUTPUT. При вызове SPI.begin() данный пин как раз настраивается на вывод. Если бы я использовал другой пин, то его следовало бы явно настроить как OUTPUT.
      2. AD9833 принимает данные бит за битом при спаде SCK, это происходит при вызове transfer или transfer16. Поэтому задержка после установки FSYNC не помешает передаче. Можно попробовать и без задержки, но периодически у меня возникали глюки, после ее добавления модуль стал работать стабильно.
      У Вас модуль не хочет работать даже с первым скетчем? И чем проверяете его работу? Осциллограф или светодиод/динамик? Последние будут работать только с прямоугольными импульсами.

      Удалить
    2. Добрый день!
      У меня Леонардо, мне приходится использовать другой пин для SS, остальные подключаю к ICSP. Работать не хочет с первым скетчем. Проверяю работу осциллографом. Насколько я понимаю, проблема у меня именно с FSYNC.
      Для проверки работы SPI делаю так:
      void loop() {
      while (1){
      SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE2));
      SPI.transfer16(0xAAAA);
      SPI.endTransaction();
      }
      }
      Наблюдаю генерацию на SCK и SDATA с половинной частотой

      Удалить
    3. Если к ICSP подключили правильно и установили режим работы пина для FSYNC, то первый скетч должен заработать. Может модуль нерабочий...

      Удалить
  2. Очень познавательный и классный проект, уважение автору. Не могли бы подробнее расписать про управление сдвигом фаз и как несколько 9833 подключать что бы многофазный генератор сделать хотя бы с фиксированным сдвигом фаз?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Мне особо нечего добавить про работу с регистрами фазы. Они 12-разрядные, что обеспечивает разрешение 2π/4096. Для того чтобы получить на выходе сдвиг PHASESHIFT в активный регистр фазы должно быть записано значение, вычисляемое по формуле: PHASEREG = PHASESHIFT*2^12 / 2π
      AD9833 имеет 2 регистра фазы, это позволяет переключаться между ними (изменяя значение управляющего бита PSELECT) для выполнения фазовой модуляции, предварительно записав в них нужные значения.
      Для изменения значения в регистре выбора фазы необходимо передать в AD9833 16-битное слово, содержащее:
      15-14 биты - 11 (признак нового значения для регистра фазы)
      13 бит - выбор регистра, в который должно быть записано новое значение (0 - PHASE0, 1 - PHASE1)
      12 бит - не используется
      11-0 биты - новое значение для регистра фазы

      При подключении нескольких AD9833 к Ардуино, думаю, встанет вопрос их синхронизации. Описанный в данной публикации модуль уже содержит кварц на 25МГц. А вот используя отдельные AD9833, можно было бы попробовать тактировать их от Ардуино. Мне попадались скетчи с использованием таймера для этих целей. Я бы попробовал вывести тактовый сигнал Ардуино на 8 цифровой пин (управляется фьюзом CKOUT) и использовать его.
      Выводы SPI SDATA и SCLK при подключении нескольких AD9833 соединяются, а для выбора активной микросхемы нужны отдельные выводы. При этом управляющие команды, например, снятие бита RESET для разрешения работы генераторов, можно подавать, установив активными сразу все подключенные AD9833.

      Удалить
  3. Можно поинтересоваться, ещё статьи планируются про различные генераторы сигналов?

    ОтветитьУдалить
    Ответы
    1. В планах написать про NE555. Хотелось бы еще написать статейку про легендарную К155ЛА3 и примеры устройств на ней, в том числе генератор.
      Если же речь о чем-то более серьезном, сопоставимом с AD9833, то такого пока в планах нет.

      Удалить
  4. Рекомендую в будущих статьях про генераторы на логике, той же ЛА3, упоминуть про расщепители фаз на счётчиках(например cd4017) и триггерах (например 74ac74). Многим интересно будет знать как из одного сигнала получить несколько сдвинутых по фазе.

    ОтветитьУдалить
  5. Можете подсказать как свип режим добавить в этот генератор? Допустим шаг частоты УЖЕ задаётся переменной FreqStep. Начальная частота УЖЕ задаётся энкодером и функцией InputFreq() , предполагаю что надо копировать этот пункт меню ну и переименовать его, допустим в OutputFreq(), в итоге появятся начальное и конечное значения. А как и главное в какое место цикл свипа правильно засунуть? Ну и конечно добавить кнопку "StartSweep" :) Заморачиваться ещё с пунктом время свипа не охота, пусть по максимуму будет, кто бы знал с какой скоростью могут значения частоты перезаписываться в ad9833?

    ОтветитьУдалить
    Ответы
    1. Тут вопрос скорее организационный: как это всё представить в меню. Потому что собственно приращение частоты через определенный промежуток времени проблемы не представляет.

      А организовать это можно, например, так: добавить в меню еще один пункт: Switch to sweep mode. При выборе этого пункта установить в программе некоторый флаг (переменную), анализ которой должен выполняться в процедуре loop: в одном случае выполняется всё то, что сейчас есть внутри loop (если, конечно, вам всё это нужно), в другом случае - вот здесь уже дописать код для свип режима.

      По большей части он будет таким же: анализ состояния энкодера, вызов меню, отображение информации на дисплее. Плюс добавится код для приращения частоты. Меню нужно будет дополнить еще одной веткой, параллельной mkRoot, например,

      {mkNull, mkRootSweep, "Menu sweep", NULL},

      И уже внутри этой ветки добавить пункты для ввода начальной/конечной частоты, времени и шага приращения и пункт Switch to normal mode – название для дисплея длинное, придется перефразировать. При выборе этого пункта наш флаг нужно будет сбросить. Ну и вызов меню здесь будет выглядеть как DrawMenu(mkRootSweep), чтобы отобразилась именно ветка для свип режима.
      Не проверял, но должно получиться, причем вполне грамотно в плане логичности интерфейса. Поняли основную идею?

      По поводу кнопки StartSweep. Можно поступить следующим образом: добавить ее в меню, при этом само меню должно вызываться не по кнопке энкодера, а всегда: вошли в loop -> проверили наш флаг и попали в блок для свип -> вызвали меню -> если выбрано не StartSweep, то выполнить что требуется и покинуть loop. При следующем заходе в loop мы снова попадем в меню и т.д. А вот если выбрали StartSweep, то тут уже делаем наш цикл с приращением, отображаем информацию на дисплее, опрашиваем энкодер. Здесь можно использовать как цикл for, так и саму функцию loop

      Если что-то непонятно, могу помочь в почте. VladimirTsibrov@yandex.ru

      Удалить
  6. Сложновато однако:) Но проект получился бы очень крутым и многим интересный. С меню вроде разобрался, смогу добавить пункты. Все ваши пункты оставлю. Думаю ввести новые функции/переменные для свипа, по большей части копировать и переименовать ваши.
    Предполагаемый алгоритм работы:
    1) Подали питание – генерация идёт, частота по умолчанию 1000 Гц, энкодер по умолчанию регулирует сотни Герц.
    2) Зашли в меню – зашли в пункт Sweep mode – flagsweep = 1 ; отображается подменю
    • “INPUT Freq” ## unsigned long InputFreq2()
    • “OUTPUT Freq” ## unsigned long OutputFreq2()
    • “Step Freq” ## mkInc копирую и добавлю шаги
    • “Time Freq” ## unsigned long TimeFreq2() в миллисекундах задавать
    • “Start sweep” ## flagsweepstart = 1; цикл пошёл
    “Stop sweep” ## flagsweepstart = 0; - надпись МЕНЯЕТСЯ когда свип запущен, служит для остановки свипа, можно и без этого.
    • “Back to gen. mode” ## flagsweep = 0; flagsweepstart = 0;

    Выставили что надо, выбрали пункт “Start sweep” – свип стартовал. Прервать свип можно только выбрав пункт “Back to gen. mode” или “Stop sweep” (если его получится сделать). Дополнительные ”железные” кнопки можно не вешать.
    Код будет около 1500 строк:) , главное его легко будет потом перенести на STM32.
    Самое интересное теперь как реализовать цикл с учётом времени? Думаю использовать цикл for как-то так for (unsigned long i= InputFreq2 ; i<= OutputFreq2; i+ FreqStep { SetFrequency (i); } А время как туда запихнуть? Цикл в цикле может? Хотел в протеусе промоделировать, а там нету ad9833((

    ОтветитьУдалить
  7. Добрый день. А какой дисплей использовался?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Обычный символьный 20x4 с I2C интерфейсом

      Удалить
  8. Здравствуйте!
    Я правильно понимаю, один I2C модуль одинаково работает как с LCD 1602, так и 2004?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Правильно. Только нужно будет скорректировать число столбцов и строк в начале скетча, возможно, изменить адрес I2C. Ну и адаптировать вывод информации на дисплей 16×2

      Удалить
  9. Этот комментарий был удален автором.

    ОтветитьУдалить
  10. У меня Arduino Nano первый сразу заработал, второй скетч не работает

    AD9833-2:15: error: variable or field 'SetForm' declared void
    AD9833-2:15: error: 'eWaveForm' was not declared in this scope
    AD9833-2.ino: In function 'void loop()':
    AD9833-2:347: error: 'SetForm' was not declared in this scope
    AD9833-2:351: error: 'SetForm' was not declared in this scope
    AD9833-2:355: error: 'SetForm' was not declared in this scope
    AD9833-2:359: error: 'SetForm' was not declared in this scope
    variable or field 'SetForm' declared void


    ОтветитьУдалить
    Ответы
    1. Судя по этим ошибкам, вы что-то изменили в скетче.
      LiquidCrystal_I2C установили? Примеры для нее компилируются?
      Какая версия IDE?

      Удалить
  11. Этот комментарий был удален автором.

    ОтветитьУдалить
  12. LiquidCrystal_I2C установил. Примеры из LiquidCrystal_I2C компилируются. Пересохранил скетч, все равно та же ошибка, компилятор выделяет строку #define bReset 0x100

    ОтветитьУдалить
  13. Скажите пожалуйста, мой генератор выдает синусоидальный и пилообразный сигналы только положительные: от 0 до 0,6 В (примерно). У вас же - от -0,3 до +0,3. Правда, я использую генератор CJMCU-9833. В этом причина?

    ОтветитьУдалить
    Ответы
    1. Я думаю он и должен выдавать 0 до 0,6 В. Он же меньше земли не может опуститься. Если поставить конденсатор должно быть -0,3 до +0,3
      Автор видимо поставил на всякий случай развязывающий конденсатор, что бы случайно не спалить выходной каскад генератора. У него и получился 0 сигнала на земле. Вы мерите напрямую - у вас сигнал между нулем и 0,6В

      Удалить
    2. Спасибо. Или еще проще: осциллограф включен в режиме AC (что и означает - через конденсатор). Просто смутили слова автора: "Обратите внимание: при генерации синусоидальных и треугольных импульсов, когда сигнал снимается с выхода ЦАП, его амплитуда изменяется в диапазоне -300мВ...300мВ".

      Удалить
    3. Согласен, максимальное значение около 0,6, минимальное чуть больше 0.
      -0.3..0.3 - это в режиме ac. Исправлю.

      Удалить
    4. Спасибо за разъяснение и оперативность.

      Удалить
  14. Разобрался arduino-1.6.х дает ошибку компиляции, arduino-1.8.х компилирует, но не грузит на плату. Но это давний конфликт arduino-1.8.х с моим ПК, я поэтому и использую arduino-1.6.5

    ОтветитьУдалить
    Ответы
    1. Да, версия 1.6.5 ругается при компиляции. В них постоянно что-то меняется, поэтому я остановился на 1.6.12.

      Удалить
  15. Этот комментарий был удален автором.

    ОтветитьУдалить
  16. Этот комментарий был удален автором.

    ОтветитьУдалить
  17. Здравствуйте ребята! Помогите разобраться. У меня всё загружается, только в конце выдаёт предукпреждение ISO C++ запрещает преобразование Строковой константы.....
    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    };

    ^

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    C:\Users\777\Downloads\AD9833_generator\AD9833_generator.ino:91:1: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    Скетч использует 10606 байт (32%) памяти устройства. Всего доступно 32256 байт.
    Глобальные переменные используют 787 байт (38%) динамической памяти, оставляя 1261 байт для локальных переменных. Максимум: 2048 байт.

    ОтветитьУдалить
    Ответы
    1. Добрый день
      Попробуйте в описании структуры sMenuItem заменить строку
      char *Caption;
      на
      const char *Caption;

      Удалить
  18. Спасибо, теперь всё загрузилось!

    ОтветитьУдалить
  19. Скетч загрузился без ошибок. Скажите Владимир, в вашем Скетче нужно ещё что то поменять? У меня подключён LCD 1602. Светятся две строки, информации нет. Заменены были столбцы и строки 20/4 на 16/2. На осциллографе идёт синусоида. Энкодер ни чего не регулирует. Только нажатием или прокруткой включает подсветку дисплея, когда она гаснет.

    #include
    // ***** I2C дисплей *****
    #include // https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
    #define cols 16
    #define rows 2
    LiquidCrystal_I2C lcd(0x27, cols, rows);

    ОтветитьУдалить
  20. Вы писали в начале комментариев, что надо как то адаптировать вывод информации на дисплей 16×2, подскажите как это сделать? Просто с ардуино в первый раз дело имею.

    ОтветитьУдалить
    Ответы
    1. Адаптировать - внести изменения с расчетом на дисплей 16*2.
      Например, у меня на дисплей выводятся частота, фаза и форма сигнала - 3 строки. Вам нужно оставить 2 (очевидно, выкинуть фазу). Для этого нужно поправить функцию LCDRepaint.
      В функции InputFreq убрать вывод заголовка, изменить позиции ввода частоты и ok/cancel. И т.д.

      Удалить
  21. Ну это у меня вряд ли получится. это надо программировать уметь и в кодах разбираться, а я только начинаю изучать и вникать, мне до этого ещё далеко. Буду просить кого нибудь что бы помогли переделать скетч под мой дисплей

    ОтветитьУдалить
  22. Всё получилось, генератор заработал без посторонней помощи, правда пришлось 2 дня разбираться и вникать. Спасибо Владимир вам за подсказки.

    ОтветитьУдалить
    Ответы
    1. Поздравляю! Начало в освоении Ардуино положено!

      Удалить
  23. Добрый день ,а можно дисплей от нокии поставить 5110, и как библиотеку добавить? Я новечёк. Заранее спосибо.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Если перепишете скетч под дисплей 5110, то можно. Иначе, конечно, ничего не заработает.

      Удалить
  24. здравствуйте пытался загрузить ваш скетч с энкодером но ничего не получилось пишет ошибку компиляции файлов

    ОтветитьУдалить
  25. Arduino: 1.6.12 (Windows 7), Плата:"Arduino Nano, ATmega328"

    C:\Users\РњРђРљРЎР?Рњ\Desktop\AD9833_generator\AD9833_generator.ino:3:100: fatal error: LiquidCrystal_I2C.h: No such file or directory

    compilation terminated.

    exit status 1
    Ошибка компиляции для платы Arduino Nano.

    пишет такое.

    ОтветитьУдалить
    Ответы
    1. У вас не установлена библиотека LiquidCrystal_I2C для работы с дисплеем. Поэтому IDE выдает ошибку при компиляции.
      Скачать библиотеку можно здесь: https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library

      Удалить
  26. сделал схему как у вас на рисунке но скетч проверку не прошел не пойму почему у вас получилось а у меня все оборудование такое же а проверку не проходит. первый скетч что у вас написан проверку у меня прошел а второй ни в какую.
    еще вопрос как по первому скетчу управлять платой или подразумевается только одна частотоа и ресет

    ОтветитьУдалить
  27. сдравствуйте владимир поставил библиотеку проверка пошла но стопорнула на lcd begin
    exit status 1
    no matching function for call to 'LiquidCrystal_I2C::begin()'

    ОтветитьУдалить
    Ответы
    1. Это потому что вы скачали не актуальную версию библиотеки по указанной мной ссылке, а какую-то древнюю из левого источника, в которой вместо begin нужно было вызывать init

      Удалить
  28. // ******************** Установить форму ********************
    void SetForm(eWaveForm val) {
    WaveForm = val;
    int16_t CntrlData;
    switch (val) {
    case wfSin: {
    CntrlData = 0;
    break;
    }
    case wfTri: {
    CntrlData = bMode;
    break;
    }
    case wfSqr: {
    CntrlData = bOpbiten | bDiv2 | bSleep12;
    break;
    }
    case wfSqr2: {
    CntrlData = bOpbiten | bSleep12;
    break;
    }
    }
    WriteAD9833(CntrlData | bCntrl_reg | bB28);
    }
    exit status 1
    'WriteAD9833' was not declared in this scope

    последняя строка выделилась и пишет ошибку практически конец скетча
    заранее спасибо владимир без вас неразберусь

    ОтветитьУдалить
    Ответы
    1. Скачайте другую версию IDE.
      У меня было подобное в версии IDE 1.6.5. Скачайте посвежее.

      Удалить
    2. У меня тоже была такая ошибка. Пришлось прописать параметры дисплея lcd.begin(20,4);

      Удалить
  29. спасибо огромное всё заработало
    скажите а можно переделать скетч для платы с ad9850 много ли придется менять

    ОтветитьУдалить
    Ответы
    1. Для ad9850 не подойдет, она по-другому управляется

      Удалить
  30. подскажите, пожалуйста, в чем схему рисовали?

    ОтветитьУдалить
  31. здравствуйте. подключил дисплей и ad9833 по схеме, как и у вас, вместо энкодера поставил кнопки. но когда я вставляю провод от компа в ардуино, экран ели светится, а сам ad9833 моментально дико нагревается. грешил на короткое замыкание, но проверил схему 3 раза и прозвонил все контакты, его нет. в чем может быть проблема?
    заранее спасибо.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Если при подключении не перепутали контакты, то похоже на неисправность модуля. Попробуйте просто подать питание на AD9833, будет ли он греться.

      Удалить
    2. Господи! ну что вы творите! В модуле энкодера стоят подтягивающие резисторы 10к на шины А, В! Бедная ваша плата...)
      Пропишите в сетапе PULLUP для энкодера и тогда спокойно юзайте об землю. А про + на кнопках забудьте вообще - это зло

      Удалить
  32. все отключил, подключил только питание на модуль, греется. спасибо за ответ

    ОтветитьУдалить
  33. Владимир, приветствую. Подскажите, LiquidCrystal_I2C по вашей ссылке, IDE 1.8.5 и 1.8.9 выдает ошибку:
    AD9833_generator:274:13: error: no matching function for call to 'LiquidCrystal_I2C::begin()'
    lcd.begin();
    Не используется: /home/andrey/Документы/Arduino/libraries/Arduino-LiquidCrystal-I2C-library-master
    exit status 1
    no matching function for call to 'LiquidCrystal_I2C::begin()'

    ОтветитьУдалить
    Ответы
    1. Добрый день.
      Скачайте актуальную версию библиотеки с гитхаба, ссылка есть в начале скетча

      Удалить
    2. Так по ней сегодня и качал

      Удалить
    3. Значит вы не удалили старую версию библиотеки, вот ide ее и использует

      Удалить
    4. Да, получилось, большое спасибо))

      Удалить
  34. Этот комментарий был удален автором.

    ОтветитьУдалить
    Ответы
    1. Добрый день.
      Боюсь, это совсем не моя тема и я не смогу с ней помочь.

      Удалить
    2. Нет так нет)) Ваш генератор попробую сделать, спасибо за схему и за скетч.

      Удалить
  35. Владимир, подскажите пожалуйста, тестовый скетч компилируется, но при загрузку выдает следующее:
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
    и так до
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
    Что нужно поправить? Хочу проверить АД 9833

    ОтветитьУдалить
    Ответы
    1. Добрый день.
      В скетче ничего править не нужно. У вас проблема в подключении Ардуино к компьютеру. Попробуйте другую плату ардуино, другой компьютер/провод/usb порт

      Удалить
    2. Виктор, спасибо за помощь. У меня почему то с тестовым скетчем АД выдает прямоугольный сигнал 400 и 200 гц. А с основным скетчем вообще ни чего не выдает, но с основным у меня экран не подключен и энкодер. При запуску основного скетча АД должна выдавать синус 100 гц? Это неисправность АД?

      Удалить
    3. Вы учитываете, что амплитуда синуса и треугольника 0..0,65В? Чем проверяете сигнал?
      Скетч генератора при включении выдает синус 100Гц, работать будет и без дисплея/энкодера

      Удалить
    4. проверял осциллографом Instrustar isds205A. Изменил амплитуду и увидел синус и треугольник. В авто режиме ни как не хотел увидеть все сигналы. Виктор, благодарю за помощь))

      Удалить
    5. Только я Владимир, а не Виктор

      Удалить
    6. Владимир, извините это я по невнимательности

      Удалить
  36. Владимир, еще вопрос, хотел собрать по вашей схеме, даже плату развел https://yadi.sk/d/LcbRcLWCy6lLug с TDA7056 только разъем питания не поставил, хотел было травить, но у меня уже есть плата по этой схеме https://easyeda.com/nikolayispolin/Ad_9833-81971df3f3d24c7799cea6b49fb2e1f0 переназначил пины энкодера, дисплей и энкодер работают, там отличия в том, что контакты AD9833 sdata подключен на A4 и sclk на A5. Как в вашем сектче переназначить пины? Смог только с энкодером разобраться

    ОтветитьУдалить
    Ответы
    1. Не получится. SPI аппаратно сидит на этих пинах, другие он использовать не может.
      Если только попробовать программный SPI. Например, есть библиотека SoftSPI, может получится с ней.

      Удалить
    2. Получается что в коде не нежно их прописывать они сами подхватываются на пинах ардуины D11,13?

      Удалить
    3. Владимир, огромная вам благодарность)

      Удалить
  37. Владимир, переделал схему по ссылке выше, собрал, все работает)) Благодарю))
    Как изменить частоту по умолчанию при запуске генератора разобрался, а вот как изменить шаг с 1гц на 1000гц на сообразил. Подскажите пожалуйста в какой строке это изменить?
    Выложил ваш скетч на форум http://arduino.ru/forum/proekty/generator-dlya-katushki-mishina?page=6#comment-459051

    Если будет время может вы посоветуете алгоритм для нахождения резонанса катушек в автоматическом режиме с помощью ina219?

    ОтветитьУдалить
    Ответы
    1. Шаг задается переменной FreqStep. В setup ей присваивается значение 1. Измените его на 1000

      Удалить
    2. Владимир, благодарю. изменил!

      Удалить
    3. Насчет ina219 - я не работал с этим датчиком. Но в целом алгоритм представляется следующим:
      В цикле изменять значение частоты от начального значения к конечному с некоторым шагом. Внутри цикла опрашиваем датчик чтобы принять решение о нахождении резонанса.
      А дальше отображение на экране, запись в EEPROM... Но вот с условием для нахождения резонанса не подскажу, т.к. не знаком с протекающими процессами.

      Удалить
  38. Владимир, а можно сделать, чтобы он при выключении запоминал предыдущее значение частоты и включался уже с этой частотой, что бы не перестраивать каждый раз его.

    ОтветитьУдалить
    Ответы
    1. Можно. В IDE Arduino есть примеры для чтения и записи в EEPROM. Посмотрите их, там всё просто.
      В скетче надо добавить считывание частоты при запуске, а запись в EEPROM я бы рекомендовал сделать отдельным пунктом в меню.

      Удалить
  39. Здравствуйте Владимир!
    Я тоже использую в одном из своих пректиков связку Arduino NANO и AD9833.
    Всё прекрасно рботает. Но в Вашем описании я увидел ВИРТУАЛЬНЫЙ ОСЦИЛЛОГРАФ и захотелось применить его для своей приблУды. Поиски на просторах и-нета дают только примитивные программки не охвтывающие диапазон АД9833. Спросить не у кого, поэтому и обращаюсь к Вам.
    Не были бы Вы любезны - поделиться Вами применённой программой или ссылкой на нее.
    Буду весьма признателен.

    С Уважением,
    Павел Сумин
    s069544367@gmail.com

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Кроме программы нужен еще сам осциллограф. Он подключается к компьютеру по usb, результат отображается в программе. Я использую ISDS205A, на Али он сейчас стоит около 50$. Есть и другие модели, посерьезнее, но мне хватает этого.

      Удалить
  40. Спасибо Владимир. Я знаю об этом и имею осциллограф ATTEN ADS1102CAL Но почему-то софт идущий в комплекте работакт настолько криво, что я вынужден искать альтернативу. Предполагаю, что отличия
    софта не должны быть принципиальными. Вот хотел попробовать софт от Вашего аппарата

    ОтветитьУдалить
  41. Владимир, добрый день. Собрал всё по схеме. Скетч загрузился. Но на дисплее хаотично разбросаны прямоугольники или полоски. Курсор передвигается нажатием на кнопку энкодера. На вращение не реагирует. По отдельности проверял все детали, всё работает. Полскажите, где искать ошибку.

    ОтветитьУдалить
    Ответы
    1. Добрый день.
      В другом комментарии вы написали, что добавили параметры в вызов lcd.begin(), чтобы избавиться от ошибки. Это говорит о том, что у вас старая версия библиотеки, в которой вместо begin нужно было вызывать функцию init. Вероятно, замена begin на init поможет избавиться от хаотичных символов, но я бы рекомендовал скачать актуальную версию библиотеки.
      Что касается энкодера, проверьте его соединение с Ардуино, к тем ли выводам он подключен

      Удалить
    2. Спасибо за помощь! Сегодня попробовал, всё работает.
      А с энкодером проблема заключалась в том, что я не готовый модуль использовал, а ставил просто энкодер с резисторами. И немного накосячил при монтаже.

      Удалить
  42. Владимир, генератор работает на вашем скетче, но при переключении в меню на меандр, меандра нет ни на какой частоте, есть только синусоида и треугольник. Не подскажите, где может быть проблема. Проверял на вашем тестовом, всё работало.

    ОтветитьУдалить
    Ответы
    1. В скетче меняли что-нибудь? И скажите версию вашей IDE.

      Удалить
    2. В скетче изменено было только то, что вы посоветовали, в описании структуры sMenuItem заменина строка
      char *Caption;
      на
      const char *Caption;
      и всё. Версия 1.8.8

      Удалить
    3. Проверьте всё еще раз, может ошиблись когда снимали меандр с генератора? Только что попробовал на 1.8.8 - всё работает.

      Удалить
  43. Товарищ из Латвии в Тelegram мне тоже пишет, что меандра нет, Вот переписка. А почему тогда на тестовом скетче все сигналы есть?

    wpd123, [12.07.19 16:29]
    C AD9833 у меня меандр не идёт, когда в меню энкодером на него переключаюсь.

    wpd123, [12.07.19 16:30]
    Идёт только синус и треугольник

    Евгений Сафронов, [12.07.19 16:30]
    Это да, у меня такая же проблема.

    wpd123, [12.07.19 16:30]
    Может со скетчем чего то не так, я с яндекс-диска его скопировал с сайта "про ардуино и не только"

    wpd123, [12.07.19 16:30]
    У тебя тоже не идёт меандр?

    Евгений Сафронов, [12.07.19 16:31]
    Не идёт, тот же скетч заливал что и ты.

    wpd123, [12.07.19 16:32]
    Я думал у меня одного такая беда, думал что с AD9833 проблема.

    ОтветитьУдалить
    Ответы
    1. Я когда разбирался с модулем обратил внимание, что он весьма капризный. У меня тоже иногда пропадал сигнал на выходе, как правило при изменении частоты энкодером. Бывало намучаешься, плюнешь, на следующий день достаешь, а он уже работает. Проблема ушла, по-моему, после добавления delayMicroseconds(1) в функцию WriteAD9833. Попробуйте увеличить здесь задержку. Может скорость пониже указать - SPI_CLOCK_DIV16.

      Удалить
    2. У меня в скетче вот так.

      void WriteAD9833(uint16_t Data) {
      SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE2));
      digitalWrite(SS, LOW);
      delayMicroseconds(1);
      SPI.transfer16(Data);
      digitalWrite(SS, HIGH);
      SPI.endTransaction();
      }

      Удалить
  44. Проверил скетч, всё правильно, проверил осциллограф все работает. На другом генераторе собранным не на ардуино, меандр выдаёт без проблем. Что интересно вначале как только был собран генератор и залит в него скетч, меандр был. Месяца 2 он лежал, руки не доходили собрать в корпус. А когда дошли, то оказалось что меандр пропал. Хотя генератор просто лежал в столе, ни кто его не трогал. Мистика какая то блин! )))

    ОтветитьУдалить
  45. Единственное что, когда был меандр, ардуино питался по USB разъёму-5 вольт от компа, через его же и скетч заливал. А сейчас я его питаю ардуино от отдельного БП-7,5 вольт через дугой его штекерный разъём. Но это наверное вряд ли будет причиной отсутствия меандра. Просто в данный момент провода USB нет проверить.

    ОтветитьУдалить
  46. Владимир, все работает прекрасно, большое вам спасибо. Возможно ли добавить функцию изменения скважности, для генератора сигналов вещь весьма необходимая ?

    ОтветитьУдалить
    Ответы
    1. AD9833 не поддерживает изменение скважности, так что добавить её не получится

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
    3. Для этого AD9833 может и не нужна (это про прямоугольные импульсы). Наверно их можно получить прямо на ардуино?

      Удалить
    4. Можно. Но это уже совсем другая история. Тут статья все-таки про AD9833.

      Удалить
  47. Наконец то собрал всё на ардуино про мини. Всё замечательно работает. Только вот вопрос- как увеличить частоту опроса энкодера? Срабатывает не на каждый щелчок.
    Т.е., если быстро крутить, то считывает только 2-4 щелчок. Остальные игнорирует.

    ОтветитьУдалить
    Ответы
    1. В функции GetEncoderState() есть условие, чтобы энкодер опрашивался не чаще 1 раза за 5мс. Попробуйте вместо 5 указать меньшее значение.

      Удалить
    2. Владимир, спасибо за ответ. Поменял значения. Не помогло. И тогда стал внимательнее следить за поведением курсора при вращении энкодера. Оказалось, что с какой бы скоростью я его не вращал, курсор реагирует лишь на каждое второе срабатывание выключателя энкодера.

      Удалить
    3. Т.е. у вас 2 импульса вместо 4 на 1 шаг энкодера? Помотрите последние комментарии в статье https://tsibrov.blogspot.com/2017/10/blog-post.html , должно ромочь.

      Удалить
  48. в 274 строке вместо begin();
    нужно писать init();
    В библиотеке l2C дисплей ей инициализируется

    ОтветитьУдалить
    Ответы
    1. Неоднократно уже писал об этом в комментариях. У вас старая версия библиотеки, скачайте актуальную из репозитория (ссылка на него есть в скетче).

      Удалить
    2. Спасибо большое за ваш проект!

      Удалить
  49. Здравствуйте, что за программа виртуального осциллографа? Можно на нее ссылку?

    ОтветитьУдалить
  50. Добрый день,можете подсказать с кодом для трапециидального сигнала на Arduino?Буду очень блягодарен.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      На AD9833 вы его не получите. Если же речь о реализации на Ардуино в принципе, то варианты есть. Я бы попробовал использовать для этого цифровой потенциометр.

      Удалить
    2. А можете дать пример кода для трапециидального сигнала на Arduino ?С синусоидальным проблем нет,а трапециидальный не получается сделать .Заренее спасибо за ваш ответ

      Удалить
    3. У меня нет такого кода. И это не то, что можно накидать за пару минут. Если готовы заплатить за работу, то на форуме ардуино найдутся желающие.

      Удалить
    4. Здравствуйте Владимир.Собрал схему как у вас с энкодером и дисплеем,библиотеку скачал по ссылке,все загрузилось но на дисплее пусто,только подсветка и энкодер только включает подсветку.Все сделал по инструкции,в чем проблема может быть.

      Удалить
    5. Добрый день!
      Раньше работали с этим дисплеем? По описанию я бы сказал, что на нем выкручена контрастность. Отрегулируйте ее подстроечным резистором на плате сзади.

      Удалить
    6. Владимир,спасибо вам огромное за проект и за помощь.Проблема была как вы и сказали в вырученной контрастности.Все заработало.

      Удалить
  51. Как писали выше в комментариях энкодер отрабатывает только 2,4 и ТД поворот.Владимир не подскажите что добавить в код чтобы энкодер работал нормально.

    ОтветитьУдалить
    Ответы
    1. то есть у вас энкодер выдает 2 импульса на шаг вместо 4, я правильно понял?
      Попробуйте заменить в скетче функцию GetEncoderState на следующую:

      eEncoderState GetEncoderState() {
      // Считываем состояние энкодера
      eEncoderState Result = eNone;
      CurrentTime = millis();
      if (CurrentTime >= (PrevEncoderTime + 5)) {
      PrevEncoderTime = CurrentTime;
      if (digitalRead(pin_Btn) == LOW ) {
      if (ButtonPrev) {
      Result = eButton; // Нажата кнопка
      ButtonPrev = 0;
      }
      }
      else {
      ButtonPrev = 1;
      EncoderA = digitalRead(pin_DT);
      EncoderB = digitalRead(pin_CLK);
      if ((!EncoderA) && (EncoderAPrev)) { // Сигнал A изменился с 1 на 0
      if (EncoderB) Result = eRight; // B=1 => энкодер вращается по часовой
      else Result = eLeft; // B=0 => энкодер вращается против часовой
      }
      else if ((EncoderA) && (!EncoderAPrev)){// Сигнал A изменился с 0 на 1
      if (EncoderB) Result = eLeft;
      else Result = eRight;
      }
      EncoderAPrev = EncoderA; // запомним текущее состояние
      }
      }
      return Result;
      }

      Сам не проверял, у меня нет таких энкодеров.

      Удалить
    2. Спасибо Владимир.Все получилось.Теперь энкодер работает как надо.

      Удалить
  52. Здравствуйте, Владимир, у меня такой же вопрос, как у Ивана, как получить две синусоиды с определенным сдвигом по фазе от двух модулей. Тактировать оба модуля можно от одного генератора с любого модуля, останавливать и запускать модули в работу можно одновременно подавая те же сигналы им на ножки, но как сделать одинаковое число в аккумуляторах фаз обоих модулей? Не нашел, как можно сбросить в ноль аккумулятор фазы модуля, а значит связать фазы заданным сдвигом не удастся. Или я что-то недосмотрел. Возможно, при запущенных модулях каким-то образом можно получить нулевой фазовый сдвиг между их сигналами? Тогда вопрос был бы решен. А может быть Вы подскажете другое решение проблемы? Заранее благодарен.
    Виктор

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Аккумулятор фазы сбрасывается при установке бита Reset. Далее загружаете нужные значения и снимаете Reset.
      Но может вам стоит посмотреть другие микросхемы-генераторы для этих целей? От Analog Devices это, например, AD9106 с 4 отдельно программируемыми выходами. Правда она уже и стоит 15$. Может есть что подешевле у других производителей.

      Удалить
  53. Вот спасибо, Владимир, выручили меня, а то я уже начал программировать двухканальный DDS на Atmega328. Мне нужен этот генератор на частоту до 4 КГц, поэтому AD9833 в самый раз. Купил для этой цели модуль AD9854, но похоже, что между выходами установлена разность фаз 90 градусов и ее нельзя менять. Здоровья Вам и удачи!

    ОтветитьУдалить
  54. Этот комментарий был удален автором.

    ОтветитьУдалить
  55. Добрый вечер, Владимир, наконец закончил работу над синтезатором на двух AD9833, тактируемых от генератора 25 МГц с одного из них. Управление сделал на PIC16F684, LCD2x16, механический валкодер, две кнопки управления. Частоту синтезатора можно менять от 1 Гц до 12,5 МГц с шагом 1 Гц, фазу между сигналами можно менять от 0 до 999.9 градусов с шагом 0.1 градуса. Все получилось. Еще раз спасибо за помощь!

    ОтветитьУдалить
    Ответы
    1. Добрый вечер!
      Отлично! Поздравляю с успешным проектом!

      Удалить
  56. Подскажите, как сделать чтобы генератор выдавал от 0 до 12 мегагерц?
    К сожалению я так и не понял как правильно задавать регистр частоты.

    ОтветитьУдалить
    Ответы
    1. Скачайте скетч, ссылку на который я привел в конце статьи. В нем есть функция
      void SetFrequency(unsigned long val)
      она устанавливает частоту сигнала, используйте ее. Там же есть функции для установки фазы и формы сигнала.

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

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Сигнал снимается с вывода OUT. Второй вывод - земля. К ним и подключен осциллограф.
      А что именно интересует в работе осциллографа?

      Удалить
    2. Спасибо за ответ!
      В работе осцилографа интересует как подключен генератор сигналов к компьютеру.
      В линейный вход напрямую с out? Или по com порту данные принимает?

      Удалить
    3. Прошлый комментарий немного не верный.
      Интересует в какой интерфейс компьютера подключаются выводы. И нужно ли какое-нибудь доп оборудование?

      Удалить
    4. Да, нужно дополнительное оборудование. Я использую Instrustar isds205A, он делает выборки и передает их в компьютер через USB. А на компьютере запускается программа, которая всё это принимает и отображает, как на скриншотах в статье.

      Погуглите по названию Instrustar isds205A. Есть и другие фирмы и модели, с бОльшим числом каналов и частотой дискретизации.

      Удалить
  58. Владимир, а вам сильно сложно добавить режим качания частоты? к примеру по маркерам? например ставишь частоту 1-го маркера 1мгц, ставишь частоту второго маркера 2.5мГц и приборчик с частотой к примеру 5 - 10гц плавно поднимает частоту, потом резко к начальной точке сбрасывает (пилообразный закон). для чего? я вашу разработочку хочу использовать как источник опорной частоты в петле ФАПЧ синтезатора частоты на ЖИГ... в качестве основного устройства используется МС12179.

    ОтветитьУдалить
  59. а так разработка просто выручила меня. я работаю с СВЧ техникой и часто нужен измерительный стабильный свч генератор, а в нем в петле ФАПЧ не обойтись без вашей разработке. В программировании я дуб - дерево хвойное...

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Можно и добавить. Попробую. Уже делал что-то такое.

      Удалить
    2. Напишите мне на VladimirTsibrov@yandex.ru Есть вопрос

      Удалить
  60. Можно спросить? собрал все по схеме, заливаю прошивку на ардуинку, но при этом инфа не отображается на дисплее, что может быть?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Если SCL и SDA не перепутали, то, скорее всего, у вас выставлен другой адрес на I2C модуле. Проверьте на нём перемычки A0, A1, A2 - они определяют I2C адрес микросхемы. По этой ссылке поймёте, какой адрес у вас:
      https://www.robotics.org.za/image/data/Display/I2C_display/LCD2004_02_address.jpg

      Адрес указывается в начале скетча в строке LiquidCrystal_I2C lcd(0x27, cols, rows);
      в данном случае 0x27

      Удалить
    2. Также адрес I2C устройства можно увидеть в I2C сканере. Заливаете в ардуинку скетч и смотрите что он пишет в мониторе порта. Скетч здесь:
      https://gist.github.com/tfeldmann/5411375

      Удалить
    3. Адрес такойже 0х27, пины не перепутаны, интересно что тогда не так(

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

      Удалить
    5. Большое спасибо, вопрос решился, дело было в подстроечном резисторе, он не был настроен.

      Удалить
  61. Здравствуйте, можно задать вопрос? Существуют ли способы увеличить амплитуду синусоидального сигнала, чтобы она был в большем диапазоне нежели указанный 38мВ...0,65В? Заранее спасибо за ответ и извиняюсь за возможно глупый вопрос.)

    ОтветитьУдалить
    Ответы
    1. И можно ли как то получить отрицательные значения?

      Удалить
    2. Добрый день!
      Штатно никак. Если только добавить в схему усилитель. Мне попадалась схема с LM318N, поищите в интернете.

      Удалить
  62. Спасибо за проект. Повторил. Работает. Подскажите, где в скетче поправить частоту при включении?

    ОтветитьУдалить
    Ответы
    1. В функции setup есть строка
      SetFrequency(100); // Установим частоту 100Гц
      Она и определяет частоту при включении.

      Удалить
    2. 2 года проекту. Как ограничить мин и макс. частоту 250-350 кгц генератора, хочу использовать его для генератора катушек Мишина только синусом, можете дописать генератор меандра 2-3 кгц с регулировкой и отображеникм на лсд. Спасибо.

      Удалить
  63. Хороший проект Владимир. Интересует вопрос чем дополнить проект, что бы стало возможно программно менять амплитуду колебаний.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Повысить амплитуду можно, добавив в схему операционный усилитель. А для её программной регулировки потребуется цифровой потенциометр. Но более конкретно по схеме я сейчас не подскажу. В будущем думаю попробовать сделать такую доработку.

      Удалить
  64. Здравствуйте Владимир. Проект безусловно хорош. Хотел спросить, а возможно сделать программно, чтобы менялась частота автоматически в заданных пределах. И через некоторое заданное количество циклов.?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Попробуйте этот скетч: https://drive.google.com/file/d/1xscj5j39uZzVHrsjgAyFoipvJjQqUON-/view?usp=sharing

      Удалить
    2. Для этого скетча нужна библиотека https://github.com/VladimirTsibrov/LiquidCrystal_I2C_Menu
      Статья про неё здесь: https://tsibrov.blogspot.com/2020/09/LiquidCrystal-I2C-Menu.html

      Удалить
  65. Владимир28 июля 2020 г., 10:31
    Добрый день!
    Повысить амплитуду можно, добавив в схему операционный усилитель. А для её программной регулировки потребуется цифровой потенциометр. Но более конкретно по схеме я сейчас не подскажу. В будущем думаю попробовать сделать такую доработку.

    Ххорошо бы под этот генератор хороший усилок доработать, что бы можно было как цепер под электроды использовать и катушки Мишина и Тесла подключать! )))

    ОтветитьУдалить
  66. В примере с LCD2004, как кажется, есть ошибка в коде.
    функция установки частоты должна выглядеть так:

    void SetFrequency(unsigned long val) {
    Freq = val;
    unsigned long FreqData = round((float) val * 10.73741 + 0.5);
    WriteAD9833((FreqData & 0x3FFF) | bFreq_reg0);
    WriteAD9833((FreqData >> 16) | bFreq_reg0);
    }

    ОтветитьУдалить
    Ответы
    1. прошу прощения, в примере на сайте правильный код.

      Удалить
  67. Доброго времени суток. Как установить частоту на сигнал?
    #include

    void setup() {
    SPI.begin();
    WriteAD9833(0x2100); //0010 0001 0000 0000 - Reset + DB28
    WriteAD9833(0x50C7); //0101 0000 1100 0111 - Freq0 LSB (4295)
    WriteAD9833(0x4000); //0100 0000 0000 0000 - Freq0 MSB (0)
    WriteAD9833(0xC000); //1100 0000 0000 0000 - Phase0 (0)
    WriteAD9833(0x2000); //0010 0000 0000 0000 - Exit Reset
    }

    void WriteAD9833(uint16_t Data){
    SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE2));
    digitalWrite(SS, LOW);
    delayMicroseconds(1);
    SPI.transfer16(Data);
    digitalWrite(SS, HIGH);
    SPI.endTransaction();
    }

    void loop() {
    WriteAD9833(0x2000); //0010 0000 0000 0000 - Синусоидальный сигнал
    delay(5000);
    WriteAD9833(0x2002); //0010 0000 0000 0010 - MODE=1 - Треугольный
    delay(5000);
    WriteAD9833(0x2020); //0010 0000 0010 0000 - OPBITEN=1 - Прямоугольный (MSB/2)
    delay(5000);
    WriteAD9833(0x2028); //0010 0000 0010 1000 - OPBITEN=1, DIV2=1 - Прямоугольный (MSB)
    delay(5000);
    }

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      В конце статьи есть ссылка на скетч. Скачайте его. В нём есть функция для установки частоты - SetFrequency

      Удалить
  68. спасибо за ответ, но я не могу понять скетч слишком сложен для мене, не могли бы вы мне показать на примере 1 из сигналов, дальше я думаю сам справлюсь.

    ОтветитьУдалить
    Ответы
    1. #include

      #define bFreq_reg0 0x4000

      void setup() {
      SPI.begin();
      WriteAD9833(0x2100); //0010 0001 0000 0000 - Reset + DB28
      SetFrequency(100); // Установим частоту 100Гц
      WriteAD9833(0xC000); //1100 0000 0000 0000 - Phase0 (0)
      WriteAD9833(0x2000); //0010 0000 0000 0000 - Exit Reset

      }

      void WriteAD9833(uint16_t Data){
      SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV2, MSBFIRST, SPI_MODE2));
      digitalWrite(SS, LOW);
      delayMicroseconds(1);
      SPI.transfer16(Data);
      digitalWrite(SS, HIGH);
      SPI.endTransaction();
      }

      void loop() {
      WriteAD9833(0x2000); //0010 0000 0000 0000 - Синусоидальный сигнал
      delay(5000);
      WriteAD9833(0x2002); //0010 0000 0000 0010 - MODE=1 - Треугольный
      delay(5000);
      WriteAD9833(0x2020); //0010 0000 0010 0000 - OPBITEN=1 - Прямоугольный (MSB/2)
      delay(5000);
      WriteAD9833(0x2028); //0010 0000 0010 1000 - OPBITEN=1, DIV2=1 - Прямоугольный (MSB)
      delay(5000);
      }

      // ******************** Установть частоту ********************
      void SetFrequency(unsigned long val) {
      unsigned long FreqData = round((float) val * 10.73741 + 0.5);
      WriteAD9833(FreqData & 0x3FFF | bFreq_reg0);
      WriteAD9833((FreqData >> 14) | bFreq_reg0);
      }

      Удалить
    2. Спасибо большое,без вас не когда не разобрался.

      Удалить
  69. Владимир большое спасибо за проект, схема сразу заработала как только залил скетч, операционник добавить будет классный сигнал на выходе. Спасибо большое!

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Благодарю за положительный отзыв. Можете посмотреть еще такой вариант скетча: https://drive.google.com/file/d/1xscj5j39uZzVHrsjgAyFoipvJjQqUON-/view?usp=sharing
      Он уже поинтереснее. Для него нужна библиотека LiquidCrystal_I2C_Menu, скачать её можно с гитхаба, ссылка и описание библиотеки здесь: https://tsibrov.blogspot.com/2020/09/LiquidCrystal-I2C-Menu.html
      При желании скетч можно адаптировать под библиотеку LiquidCrystal_I2C_Menu_Btns - она вместо энкодера использует кнопки. Кроме того обе библиотеки поддерживают кириллицу. Так что если купите дисплей, поддерживающий её, можно будет русифицировать меню.

      Удалить
  70. Добрый день, а два генератора на одну ардуину получится?

    ОтветитьУдалить
    Ответы
    1. В какую сторону копать?

      Удалить
    2. У AD9833 есть вывод FSYNC (выбор микросхемы). Подключаете обе микросхемы по приведенной схеме, только FSYNC подсоединяете к разным пинам Ардуино. При передаче данных выбираете нужную микросхему, установив на ее выводе FSYNC низкий уровень.

      Удалить
    3. Нужно переделать скетч под Atmega328PB, а там уже 2 spi. Тоже жду такого проекта. Если кто встречал, то дайте линк.

      Удалить
    4. Здесь нет необходимости во втором SPI. Интерфейс подразумевает подключение к ведущему нескольких ведомых устройств. Выбор ведомого осуществляется сигналом SS (Select Slave), в данном случае это FSYNC.
      Поэтому вопрос подключения двух (трех,...) AD9833 к Ардуино сводится исключительно к их поддержке в самой программе.

      Удалить
    5. Тоисть с помощью fsync два генератора на ад9833 будуть работать одновремннно? А можете подправить скетч? Думаю много радиолюбителей будут Вас благодарить

      Удалить
    6. Тут не то чтобы подправить, тут делать надо. С этим лучше обратиться на какой-нибудь форум радиолюбительский. Может найдутся энтузиасты

      Удалить
  71. У меня вопрос, как можно менять амплитуду сигнала синусоиды? Собственно мне нужно получить синусоиду с частотой 5МГц а амплитуда изменялась по нарастающей пиле. Спасибо

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Амплитуда в этом генераторе не регулируется. Думаю, для этих целей подойдет операционный усилитель.
      Будет время - доведу схему и скетч до ума.

      Удалить
  72. Если поставить механический переключатель между двумя ад9833 на fsync и переключать, будет ли работать 2 генератора одновремннно на 2 частотах с возможностью их изменения?

    ОтветитьУдалить
    Ответы
    1. Должно работать. Но вам точно подойдёт такой вариант? Попробуйте.

      Удалить

  73. Ошибка Компиляции, вроде все перечитал.
    Иде 1.6.12
    Если не трудно объясните что с этим делать я новечек в ардуино, но генератор очень нужен для катушек.
    C:\Users\user\Downloads\AD9833_generator\AD9833_generator.ino: In function 'void setup()':

    AD9833_generator:277: error: expected ';' before 'lcd'

    lcd.backlight();

    ^~~

    exit status 1
    expected ';' before 'lcd'

    ОтветитьУдалить
    Ответы
    1. В начале скетча есть ссылка на библиотеку LiquidCrystal_I2C. Её используете или какую-то другую?
      https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library

      Удалить
    2. Вообще, судя по сообщению компилятора, не хватает точки с запятой перед указанной строкой. Может удалили случайно? У меня в 1.6.12 всё компилируется.
      И ответ "Ссылки только ваши" не очень понятен. Ссылки тут ни при чём. Речь о том, что в IDE должна быть установлена именно эта библиотека, а не какая-нибудь другая, которая может отличаться и быть причиной ошибок при компиляции

      Удалить
  74. Отличный генератор, огромное спасибо! Все собрал, настроил. Работает на ура.

    ОтветитьУдалить
    Ответы
    1. Попробуйте ещё такой скетч, он поинтереснее:
      https://drive.google.com/file/d/1xscj5j39uZzVHrsjgAyFoipvJjQqUON-/view?usp=sharing

      Для него нужна библиотека:
      https://github.com/VladimirTsibrov/LiquidCrystal_I2C_Menu
      Статья про неё здесь:
      https://tsibrov.blogspot.com/2020/09/LiquidCrystal-I2C-Menu.html

      Удалить
  75. Здравствуйте, Владимир.Очень понравился ваш проект генератора на ad9833.
    Хочу на его основе и себе сделать функциональный генератор,в связи с чем у меня возник такой вопрос.Владимир, насколько сложно изменить прошивку так, чтобы при выборе формы сигнала,Arduino выдавала логическую единицу (высокий потенциал) на одном из выводов.Например, при выборе синуса Arduino выдаёт логическую единицу на D1,при выборе треугольника - на D2 и так далее.
    По сути я хочу сделать, чтобы Arduino коммутировала выходные усилители и фильтры.Владимир, желаю Вам творческих успехов и удачи в ваших начинаниях. С уважением Александр.

    ОтветитьУдалить
  76. Добрый день!
    Такое сделать несложно:
    1. Откройте скетч и найдите в нём функцию void SetForm(eWaveForm val), она почти в самом низу.
    2. В этой функции есть несколько блоков case для каждой из форм сигнала. Добавьте в каждый из блоков установку "1" на нужном цифровом выводе, на остальных выводах установите "0". Должно получиться что-то вроде этого:

    switch (val) {
    case wfSin: {
    CntrlData = 0;
    digitalWrite(pinTRI, 0);
    digitalWrite(pinSQR, 0);
    digitalWrite(pinSIN, 1);
    break;
    }
    case wfTri: {
    digitalWrite(pinSIN, 0);
    digitalWrite(pinSQR, 0);
    digitalWrite(pinTRI, 1);
    CntrlData = bMode;
    break;
    }
    ...

    Значения pinSIN, pinTRI и pinSQR нужно объявить где-нибудь в начале скетча.

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

    ОтветитьУдалить