Генератор adf4351 arduino

Musgravehill

Здравствуйте.
В соседней теме про мостовой КСВ-метр понадобился источник сигнала. Модули телеметрии и nrf24 не особо подходят, потому что имеют скважность.

Это попытка сделать генератор синуса на adf4351.

Жду такой модуль banggood.com/35M-4_4GHz-PLL-RF-Signal-Source-Frequ…

Пока только могу проверять интерфейс, придумывать коробочку и печатку под нее.

Не знаю, коробку пластиковую или металл. А если металл, то на корпус крепить только SMA, а землю разъема питания изолировать, наверное? Чтобы не было земляных петель.

На модуле adf4351 стоит AMS 3.3V - она будет использоваться также для питания Ардуино. Входное питание будет 5В через фильтры на эту AMS 3v3.

6 регистров управления, генерируемые в коде Ардуино совпадают с регистрами в программе.exe от AD eval board soft.

Теоретически, можно вывести rx tx Ардуино и сделать задание частоты\шага с компьютера. Т.е. написать дополнительный софт для ПК, чтобы управлять генератором не только кнопками\энкодером, но и через оболочку. Например, сделать панорамный измеритель КСВ.

====================================================================

Панкратов Сергей тоже работает над генератором для NWT4000.
По этой ссылке серьезный подход и результат :
forum.vhfdx.ru/eteo-teato/adf4350/msg315403/#msg31…

Musgravehill

Попробую по картинке #1.
На генераторе раздельные аналоговое и цифровое питание, соединяются дросселем 100uH.
С гребенки на плате генератора уходит 3.3В цифрового питания - отправлю его на Ардуино.

На шину SPI поставлю дроссели Murata BLM18GG471.

По питанию от платы генератора к Ардуино: Murata BLM18GG471 и NFM21CC223R, несколько смд-конденсаторов. Земля между генератором и Ардуино напрямую. 3.3В и землю пропущу через ферритовое кольцо (синфазный дроссель).

Земляной провод и шлейф SPI будут в одном плотном жгуте, чтобы между линиями SPI и земляным проводом не было петель (рамки).

Может, +3.3В, землю и SPI вместе пропустить через ферритовое кольцо?

Musgravehill

Пока сделал интерфейс. Самой платы adf еще нет…

Gapey

в идеале иметь возможность подключить два генератора к одному интерфейсу + два канала ацп и интерфейс к компу с протоколом WinNWT …
поддержка по возможности adf4350/adf4351/adf4356/max2871 …
в результате получим контроллер намного более функциональный - от простого генератора и КСВметра до интерфейса спектроанализатора …
ВЧ часть каждый сможет купить/сделать по вкусу/необходимости … есть много готовых вариантов генераторов и детекторов … так-же можно использовать стабилизированные задающие генераторы … можно сделать умножители и смесители на нужные диапазоны …

Панкратов_Сергей
Gapey:

генератора к одному интерфейсу + два канала ацп и интерфейс к компу с протоколом WinNWT …
поддержка по возможности adf4350/adf4351/max2871 …
в результате получим контроллер намного более функциональный - от простого генератора и КСВметра до интерфейса спектроанализатора …
ВЧ часть каждый сможет купить/сделать по вкусу/необходимости … есть много готовых вариантов генераторов и детекторов … так-же можно использовать стабилизированные задающие генераторы … можно сделать умножители и смесители на нужные диапазоны …

На все нам нужные диапазоны, в том числе и с умножителями и с фильтрами ( без фильтров не будет точности измерений , ксв менее 1.6-1.8 не оценить ) давненько делал. И выкладывал код для работы с WinNWT.
Тут набор на нужные диапазоны-

Тут вид на компе при работе с WinNWT

Тут варианты для 5.8 ггц.

А тут на базе универсальной платы Продвинутого 2 генератор 137-4400 мгц с управлением частотой, мощностью-

Musgravehill
Gapey:

в идеале иметь возможность подключить два генератора к одному интерфейсу + два канала ацп и интерфейс к компу с протоколом WinNWT …
поддержка по возможности adf4350/adf4351/adf4356/max2871

Ого! 2 генератора = отладка SPI, чтобы дергать LE на каждом.
max2871 - только слышал про них, купить довольно сложно\дорого.
Зато adf4351 на каждом шагу и доступно.

В текущей версии доступны A6, A7 и несколько цифровых, а также rx-tx.
Можно сделать так:
Напряжение с детектора (Н.О.) или перекоса резистивного моста масштабировать на операционнике и подать на А6.
Или на ЦАП и потом i2c.
Выставляем частоту, шаг. Крутим энкодер.
По TX бегут изменяющиеся freq;voltage;
Далее пишем простую программу, которая нормирует и строит график.

Но вначале запустить бы генератор,который ползет из Китая.

Панкратов_Сергей
Musgravehill:

Ого! 2 генератора = отладка SPI, чтобы дергать LE на каждом.

А что там отлаживать?
ССылка ж на мой код есть, банальное дерганье ногами, у меня все программное-

//#define P_LE 6 PD6
//#define P_DATA 8 PB0
//#define P_SCK 9 PB1

PORTD &= ~0b01000000;// 0 на LE
for (int n=0; n<4; n++)
{ // с старшего байта до младшего
byte data= Reg [num_reg] [n]; // берем байт
for (char u=0; u<8; u++)
{ //перебираем с старшего бита по младший
if(data &(0b10000000>>u)) PORTB |= 0b00000001; // ставим 1
else PORTB &= ~0b00000001; // или 0 в PB0
//обозначим clock
PORTB |= 0b00000010;// 1 дергаем PB1
PORTB &= ~0b00000010;}// 0
}
PORTD |= 0b01000000;// 1 in LE

Да и вообще какой смысл что то заново изобретать- весь код рабочий, схемы рабочие, плата так же.
Трудятся уже множество устройств…
Мне когда то пришлось изобретать, изучать протоколы- в инете не было примеров кодов.
А сейчас какой смысл?

Musgravehill
Панкратов_Сергей:

Да и вообще какой смысл что то заново изобретать- весь код рабочий, схемы рабочие, плата так же.

У меня все параметры доступны для настройки по даташиту. Это замедляет цикл, но позволяет “в лоб” дорабатывать код.

void ADF4351_prepareConfig() {
  // PLL-Reg-R0         =  32bit
  // Registerselect        3bit
  // int F_Frac = 4;       // 12bit
  // int N_Int = 92;       // 16bit
  // reserved           // 1bit

  // PLL-Reg-R1         =  32bit
  // Registerselect        3bit
  //int M_Mod = 5;        // 12bit
  int P_Phase = 1;     // 12bit bei 2x12bit hintereinander pow()-bug !!
  uint8_t Prescal = 0;     // 1bit geht nicht ???
  uint8_t PhaseAdj = 0;    // 1bit geht auch nicht ???
  // reserved           // 3bit

  // PLL-Reg-R2         =  32bit
  // Registerselect        3bit
  uint8_t U1_CountRes = 0; // 1bit
  uint8_t U2_Cp3state = 0; // 1bit
  uint8_t U3_PwrDown = 0;  // 1bit
  uint8_t U4_PDpola = 1;    // 1bit
  uint8_t U5_LPD = 0;       // 1bit
  uint8_t U6_LPF = 1;       // 1bit 1=Integer, 0=Frac not spported yet
  uint8_t CP_ChgPump = 7;     // 4bit
  uint8_t D1_DoublBuf = 0; // 1bit
  //  int R_Counter = 1;   // 10bit
  //  int RD1_Rdiv2 = 0;    // 1bit
  //  int RD2refdoubl = 0; // 1bit
  uint8_t M_Muxout = 0;     // 3bit
  uint8_t LoNoisSpur = ADF4351_lowNoiseOrSpurVariants[ADF4351_lowNoiseOrSpur_current];      //0   2bit
  // reserved           // 1bit

  // PLL-Reg-R3         =  32bit
  // Registerselect        3bit
  int D_Clk_div = 150; // 12bit
  uint8_t C_Clk_mode = 0;   // 2bit
  //  reserved          // 1bit
  uint8_t F1_Csr = 0;       // 1bit
  //  reserved          // 2bit
  uint8_t F2_ChgChan = 0;   // 1bit
  uint8_t F3_ADB = 0;       // 1bit
  uint8_t F4_BandSel = 0;  // 1bit
  //  reserved          // 8bit

  // PLL-Reg-R4         =  32bit
  // Registerselect        3bit
  uint8_t D_out_PWR = ADF4351_outputPowerVariants[ADF4351_outputPower_current] ;    // 2bit
  uint8_t D_RF_ena = 1;     // 1bit
  uint8_t D_auxOutPwr = 0;  // 2bit
  uint8_t D_auxOutEna = 0;  // 1bit
  uint8_t D_auxOutSel = 0;  // 1bit
  uint8_t D_MTLD = 0;       // 1bit
  uint8_t D_VcoPwrDown = 0; // 1bit 1=VCO off

  //  int B_BandSelClk = 200; // 8bit

  uint8_t D_RfDivSel = 3;    // 3bit 3=70cm 4=2m
  uint8_t D_FeedBck = 1;     // 1bit
  // reserved           // 8bit

  // PLL-Reg-R5         =  32bit
  // Registerselect     // 3bit
  // reserved           // 16bit
  // reserved     11    // 2bit
  // reserved           // 1bit
  uint8_t D_LdPinMod = 1;    // 2bit muss 1 sein
  // reserved           // 8bit

  // Referenz Freg Calc
  //  long ADF4351_referenceFreq = 250000; // Refrenquarz = 25000000hz
  int R_Counter = 1;   // 10bit
  uint8_t RD1_Rdiv2 = 0;    // 1bit
  uint8_t RD2refdoubl = 0; // 1bit
  int B_BandSelClk = 200; // 8bit
  //  int F4_BandSel = 0;  // 1bit

  // int F4_BandSel = 10.0 * B_BandSelClk / PFDFreq;

  uint32_t RFout = ADF4351_frequency;   // VCO-Frequenz
  // calc bandselect und RF-div
  uint8_t outdiv = 0;

  if (RFout >= 220000000) {
    outdiv = 1;
    D_RfDivSel = B0;
  }
  if (RFout < 220000000) {
    outdiv = 2;
    D_RfDivSel = B001;
  }
  if (RFout < 110000000) {
    outdiv = 4;
    D_RfDivSel = B010;
  }
  if (RFout < 55000000) {
    outdiv = 8;
    D_RfDivSel = B011;
  }
  if (RFout < 27500000) {
    outdiv = 16;
    D_RfDivSel = B100;
  }
  if (RFout < 13800000) {
    outdiv = 32;
    D_RfDivSel = B101;
  }
  if (RFout < 6900000) {
    outdiv = 64;
    D_RfDivSel = B110;
  }

  float PFDFreq = ADF4351_referenceFreq * ((1.0 + RD2refdoubl) / (R_Counter * (1.0 + RD1_Rdiv2))); //Referenzfrequenz *10 (все частоту сокращена в 10раз почему-то)
  float N = ((RFout) * outdiv) / PFDFreq;
  uint16_t N_Int = N;
  uint16_t M_Mod = PFDFreq * (100000 / ADF4351_freqStepCurrent) / 100000;
  uint16_t F_Frac = round((N - N_Int) * M_Mod);

  ADF4351_registers[0] = (unsigned long)(0 + F_Frac * pow(2, 3) + N_Int * pow(2, 15));
  ADF4351_registers[1] = (unsigned long)(1 + M_Mod * pow(2, 3) + P_Phase * pow(2, 15) + Prescal * pow(2, 27) + PhaseAdj * pow(2, 28));
  //  ADF4351_registers[1] = (ADF4351_registers[1])+1; // Registerselect adjust ?? because unpossible 2x12bit in pow() funktion
  ADF4351_registers[2] = (unsigned long)(2 + U1_CountRes * pow(2, 3) + U2_Cp3state * pow(2, 4) + U3_PwrDown * pow(2, 5) + U4_PDpola * pow(2, 6) + U5_LPD * pow(2, 7) + U6_LPF * pow(2, 8) + CP_ChgPump * pow(2, 9) + D1_DoublBuf * pow(2, 13) + R_Counter * pow(2, 14) + RD1_Rdiv2 * pow(2, 24) + RD2refdoubl * pow(2, 25) + M_Muxout * pow(2, 26) + LoNoisSpur * pow(2, 29));
  ADF4351_registers[3] = (unsigned long)(3 + D_Clk_div * pow(2, 3) + C_Clk_mode * pow(2, 15) + 0 * pow(2, 17) + F1_Csr * pow(2, 18) + 0 * pow(2, 19) + F2_ChgChan * pow(2, 21) +  F3_ADB * pow(2, 22) + F4_BandSel * pow(2, 23) + 0 * pow(2, 24));
  ADF4351_registers[4] = (unsigned long)(4 + D_out_PWR * pow(2, 3) + D_RF_ena * pow(2, 5) + D_auxOutPwr * pow(2, 6) + D_auxOutEna * pow(2, 8) + D_auxOutSel * pow(2, 9) + D_MTLD * pow(2, 10) + D_VcoPwrDown * pow(2, 11) + B_BandSelClk * pow(2, 12) + D_RfDivSel * pow(2, 20) + D_FeedBck * pow(2, 23));
  ADF4351_registers[5] = (unsigned long)(5 + 0 * pow(2, 3) + 3 * pow(2, 19) + 0 * pow(2, 21) + D_LdPinMod * pow(2, 22));
}
Панкратов_Сергей

По моему у меня меньше строчек во всем коде , то есть всего прибора…
Работа с синтезатором, с детектором и прогой на компе с WinNWT.

Зачем переписывать весь даташит в прогу если в проге нужно 5% из него?

Musgravehill
Панкратов_Сергей:

Зачем переписывать весь даташит в прогу если в проге нужно 5% из него?

Сейчас нужно 5%, а потом 3 или 89.

Да и подстановка бит по нужным адресам - тоже неочевидное дело.
Поменялся кварц, захотелось менять мощность или low-noise-mode\low-spur-mode - надо ковыряться в битах.
Еще AD советуют избегать малого шага при низких частотах, когда дробление высокое - это можно удобно отследить по формулам в коде.

Вообще, я делаю ради энкодера и экранчика. Чтобы автономно выставлять частоту и быстро бегать с шагом N.
Фактически, коробочка на батарейках 35-4400 МГц или даже 8800 с усилителем и умножителем.

Репозиторий bitbucket.org/boris_n/ant/src

Панкратов_Сергей
Musgravehill:

Сейчас нужно 5%, а потом 3 или 89.

Может задачу вы другую ставите…
Одно дело писать библиотеку под синтезатор на все случаи жизни
Другое дело - под планируемые задачи.
Второй случай- мой. Но я, честно говоря, не представляю того что вам может понадобиться от синтезатора, но что не реализовано в моем коротком коде.

Gapey

конкретно моя хотелка - получить аналог NWT6000 , только более правильный …
в NWT6000 не устраивает то что его продают только в корпусном исполнении с пачкордами и переходниками для вывода входа/выхода на переднюю панель устройства которые придется просто выкинуть … и смеситель там явно не на диапазон 6 ГГц …
поэтому хочется модульную конструкцию , как у Сергея , но именно с двумя отдельными генераторами (второй как гетеродин) …
если оно еще и в автономе будет работать , хотя бы как генератор и КСВметр будет вообще замечательно …

у Сергея я приобрел умножитель и несколько пустых плат под генераторы и детекторы , но вот так и не нашел исходники прошивок под атмегу …

Musgravehill
Gapey:

но именно с двумя отдельными генераторами (второй как гетеродин)

ADF4351 в качестве гетеродина? Многие пишут про его фазовый шум, спуры, “неудачные” точки в диапазоне частот и китайский кварц 25МГц.

Я надеюсь, что без фильтров он сгодится как генератор “шума” более-менее конкретной частоты для прогонки антенны.

Gapey
Панкратов_Сергей:

исходник прицеплен к сообщению

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

Musgravehill:

ADF4351 в качестве гетеродина?

ну я планирую всетаки использовать max2871 …
тут на фото плпта препарированного NWT6000 на максах
uglyduck.ath.cx/PDF/MiniVNA/NWT6000_PCB.jpg

в его предшественниках NWT4000 стояли adf4350 или adf4351 (их последний год производят на платах маркированных как NWT6000)
верхний Макс используется как генератор а нижний как гетеродин … под ним смеситель в соике 😵
чтобы просто посмотреть спектр adf4351 в качестве гетеродина вполне достаточно … о каких-то точных измерениях тут конечно речь не идет …

Musgravehill
Gapey:

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

У чипа ADF есть пин LE, который переключает режимы “запись регистров через SPI” \ “рабочий режим”.
Если поставить 2 чипа, то на Ардуино (атмега, кому что привычнее) нужно выделить 2 ножки под 2 LE.
Конфигурация SPI для всех общая (делитель, порядок байт).
Дергаем LE_1, заливаем регистры.
Дергаем LE_2, заливаем регистры.
Это в теории…

Топология NWT6000 - дорогая. Явно не хоббийная в sprint-layout. Да и “рассыпуха” должна быть, иначе покупать ленты по 10-500 деталей накладно.
На Али искал резисторы 49R9 0402\0603, минимальный заказ 500 штук! Хобби накладное.

Gapey

нужно в первую очередь смотреть протокол WINNWT и добавлять обработку команд для второго генератора … а прицепить физически к атмеге не проблема, хоть через LE , хоть на отдельные ноги , свободных ног навалом …
нарисовать такую плату в спринте не сложнее чем в любом другом CAD … расчитывается ширина вч дорожек и зазоры до земляных полигонов под конкретный материал платы и рисуется согласно расчетам … там не так много критичных участков … и кстати там далеко не все грамотно сделано …
вот и хочу сделать модульный вариант …

вообще этих плат три вида

  1. самый грамотный тот что я давал ссылку на фото ( с разЪёмами торчащими вверх из платы)
  2. почти тожсамое но разЪёмы выведены на край платы … в этой версии какие то проблемы с наводками , для устранения народ лепит на крышки вч болков пружинные контакты на металлический корпус прибора …
  3. с одним генератором (он и генератор и гетеродин , чсто сильно сужает его возможности ) и разЪёмами на край платы …
Musgravehill:

На Али искал резисторы 49R9 0402\0603, минимальный заказ 500 штук! Хобби накладное.

при грамотном подходе не очень накладное … для начала закупаются библиотеки элементов R/C/L по 100 штук каждого номинала всех нужных типоразмеров (0402/0603/0805) дальше отдельно закупаются ходовые и специализированные номиналы 1uF , 0.1uF , 0.01Uf , 0.001Uf , 10k , 4.7k , 1k , 0r , 49r9 и так далее в зависимости от востребованности в проектах … 49r9 0603 у меня лежит бобина 5000 штук вообщем как и всего ходового …
а самые ходовые у меня 0.1uFx50v , их больше 1000 в год уходит …

Панкратов_Сергей
Gapey:

нужно в первую очередь смотреть протокол WINNWT и добавлять обработку команд для второго генератора …

А зачем NWT даже знать о том есть там второй-третий генератор?
NWT к тому как выполнен сам прибор никакого отношения не имеет.
Просто чуть меняется математика в коде и все, совсем немного.
То есть совсем проблем нет, все что нужно- в моем коде есть…

Musgravehill
Gapey:

нарисовать такую плату в спринте не сложнее чем в любом другом CAD … расчитывается ширина вч дорожек и зазоры до земляных полигонов под конкретный материал платы и рисуется согласно расчетам

Я взял FR4 1.6мм, у него диэлектрическая константа сигма-эр Er от 4.0 до 4.9 как повезет.
Калькулятор chemandy.com/…/coplanar-waveguide-with-ground-calc…
Чтобы получить 50R копланар с землей, нужно дорожку делать 1.85мм и зазоры 0.36мм, что многовато для 0603 смд.

Вот если бы FR4 0.8мм, тогда дорожки шириной 1.0мм - как раз мелкие СМД торцом встают.

Gapey
Musgravehill:

Чтобы получить 50R копланар с землей, нужно дорожку делать 1.85мм и зазоры 0.36мм, что многовато для 0603 смд.

я бы в первую очередь смотрел на рекомендации производителя SMA разЪёма который будет использоваться так чтобы был минимум потерь …

Musgravehill:

Вот если бы FR4 0.8мм, тогда дорожки шириной 1.0мм - как раз мелкие СМД торцом встают.

ну так а в чем проблема ??? материал доступен в широком ассортименте , параметры материалов которые в наличии в данный момент можно уточнить у изготовителя плат …
www.pselectro.ru/materialy_pechatnyh_plat/

Панкратов_Сергей:

То есть совсем проблем нет, все что нужно- в моем коде есть…

значит нужно распечатать и внимательно почитать с карандашиком …