Уважаемые посетители! Форум CQHAM.RU существует исключительно за счет показа рекламы. Мы будем благодарны, если Вы не будете блокировать рекламу на нашем Форуме. Просим внести cqham.ru в список исключений для Вашего блокировщика рекламы.
Страница 1 из 6 1234 ... ПоследняяПоследняя
Показано с 1 по 10 из 51

Тема: AD9850 - помеха-щелчок на выходе в момент запоминания частоты

  1. #1

    AD9850 - помеха-щелчок на выходе в момент запоминания частоты

    Всем привет, собрал синтезатор на DDS модуле с AD9850 + ардуино нано-3 по "классической" схеме. Вот скетч:

    Скрытый текст

    /*
    Main code by Richard Visokey AD7C - www.ad7c.com
    Revision 2.0 - November 6th, 2013
    */

    // Include the library code
    #include <LiquidCrystal.h>
    #include <rotary.h>
    #include <EEPROM.h>

    //Setup some items
    #define W_CLK 8 // Pin 8 - connect to AD9850 module word load clock pin (CLK)
    #define FQ_UD 9 // Pin 9 - connect to freq update pin (FQ)
    #define DATA 10 // Pin 10 - connect to serial data load pin (DATA)
    #define RESET 11 // Pin 11 - connect to reset pin (RST)
    #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
    Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins.
    LiquidCrystal lcd(12, 13, 7, 6, 5, 4); // I used an odd pin combination because I need pin 2 and 3 for the interrupts.
    int_fast32_t rx=3650000; // Base (starting) frequency of VFO. This only loads once. To force load again see ForceFreq variable below.
    int_fast32_t rx2=1; // variable to hold the updated frequency
    int_fast32_t increment = 10; // starting VFO update increment in HZ.
    int_fast32_t iffreq = 0; // Intermedite Frequency - Amount to subtract (-) from base frequency. ********************************************
    int buttonstate = 0;
    int buttonstate2 = 0;
    int GoIF = 1;
    String hertz = "10 Hz";
    int hertzPosition = 5;
    byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Placeholders
    String freq; // string to hold the frequency
    int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup
    int memstatus = 1; // value to notify if memory is current or old. 0=old, 1=current.


    int ForceFreq = 0; // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory. YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET!



    void setup() {
    pinMode(A0,INPUT); // Connect to a button that goes to GND on push
    pinMode(A5,INPUT); // IF sense **********************************************
    digitalWrite(A0,HIGH);
    digitalWrite(A5,HIGH);
    lcd.begin(16, 2);
    PCICR |= (1 << PCIE2);
    PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
    sei();
    pinMode(FQ_UD, OUTPUT);
    pinMode(W_CLK, OUTPUT);
    pinMode(DATA, OUTPUT);
    pinMode(RESET, OUTPUT);
    pulseHigh(RESET);
    pulseHigh(W_CLK);
    pulseHigh(FQ_UD); // this pulse enables serial mode on the AD9850 - Datasheet page 12.
    lcd.setCursor(hertzPosition,1);
    lcd.print(hertz);

    // Load the stored frequency
    if (ForceFreq == 0) {
    freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
    rx = freq.toInt();
    }
    }

    void loop() {
    // Update the display and frequency if the new Freq NEQ the old Freq
    if (rx != rx2){
    showFreq();
    sendFrequency(rx);
    rx2 = rx;
    }

    // Rotate through the rate of tuning as you hold down the button
    buttonstate = digitalRead(A0);
    if(buttonstate == LOW) {
    setincrement();
    };

    // Check for PIN low to drive IF offset Freq
    buttonstate = digitalRead(A5);
    if (buttonstate != buttonstate2){
    if(buttonstate == LOW) {
    lcd.setCursor(15,1);
    lcd.print(".");
    GoIF = 0;
    buttonstate2 = buttonstate;
    sendFrequency(rx);
    }
    else{
    lcd.setCursor(15,1);
    lcd.print(" ");
    GoIF = 1;
    buttonstate2 = buttonstate;
    sendFrequency(rx);
    };
    };

    // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change.
    if(memstatus == 0){
    if(timepassed+2000 < millis()){
    storeMEM();
    }
    }

    }


    // Interrupt routine to catch the rotary encoder
    ISR(PCINT2_vect) {
    unsigned char result = r.process();
    if (result) {
    if (result == DIR_CW){rx=rx+increment;}
    else {rx=rx-increment;};
    if (rx >=30000000){rx=rx2;}; // UPPER VFO LIMIT
    if (rx <=1000000){rx=rx2;}; // LOWER VFO LIMIT
    }
    }

    // frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
    void sendFrequency(double frequency) {
    if (GoIF == 1){frequency=frequency-iffreq;}; //If pin = low, subtract the IF frequency.
    int32_t freq = frequency * 4294967295/125000000; // note 125 MHz clock on 9850. You can make 'slight' tuning variations here by adjusting the clock frequency.
    for (int b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
    }
    tfr_byte(0x000); // Final control byte, all 0 for 9850 chip
    pulseHigh(FQ_UD); // Done! Should see output
    }
    // transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
    void tfr_byte(byte data)
    {
    for (int i=0; i<8; i++, data>>=1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high
    }
    }

    void setincrement(){
    if(increment == 10){increment = 100; hertz = "100 Hz"; hertzPosition=5;}
    else if (increment == 100){increment = 1000; hertz="1 Khz"; hertzPosition=6;}
    else if (increment == 1000){increment = 1000000; hertz="1 Mhz"; hertzPosition=6;}
    else{increment = 10; hertz = "10 Hz"; hertzPosition=5;};
    lcd.setCursor(0,1);
    lcd.print(" ");
    lcd.setCursor(hertzPosition,1);
    lcd.print(hertz);
    delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
    };

    void showFreq(){
    millions = int(rx/1000000);
    hundredthousands = ((rx/100000)%10);
    tenthousands = ((rx/10000)%10);
    thousands = ((rx/1000)%10);
    hundreds = ((rx/100)%10);
    tens = ((rx/10)%10);
    ones = ((rx/1)%10);
    lcd.setCursor(0,0);
    lcd.print(" ");
    if (millions > 9){lcd.setCursor(1,0);}
    else{lcd.setCursor(2,0);}
    lcd.print(millions);
    lcd.print(".");
    lcd.print(hundredthousands);
    lcd.print(tenthousands);
    lcd.print(thousands);
    lcd.print(".");
    lcd.print(hundreds);
    lcd.print(tens);
    lcd.print(ones);
    lcd.print(" Mhz ");
    timepassed = millis();
    memstatus = 0; // Trigger memory write
    };

    void storeMEM(){
    //Write each frequency section to a EPROM slot. Yes, it's cheating but it works!
    EEPROM.write(0,millions);
    EEPROM.write(1,hundredthousands);
    EEPROM.write(2,tenthousands);
    EEPROM.write(3,thousands);
    EEPROM.write(4,hundreds);
    EEPROM.write(5,tens);
    EEPROM.write(6,ones);
    memstatus = 1; // Let program know memory has been written
    };




    Скетч базовый от Richard Visokey AD7C, в нём изменил только: - стартовую частоту, убрал добавку для ПЧ (т.к. у меня трансивер прямого преобразования) и убрал лишние значения шага перестройки частоты, оставил 10Гц, 100Гц, ,1кГц и 1Мгц. И вот, есть проблема. Код написан так, что через 2 секунды после прекращения вращания энкодера - идёт запоминание частоты. И вот, в момент этого запоминания, в выходной сигнал попадает неприятный "бип", послушайте: https://yadi.sk/d/nKaawkvF37hfmo

    Что изменить в коде, чтобы избавиться это этого?

    p.s. время, через которое запоминается последняя частота - 2000мс записано в этих строчках:

    // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change.
    if(memstatus == 0){
    if(timepassed+2000 < millis()){
    storeMEM();

    Пробовал поставить значение 0 - "бимкает" сразу, как только вращаешь энкодер, то есть на каждое срабатывание энкодера - бип.


  2. #2
    Попробуйте оставить конденсатор и диод по питанию проца и запоминать частоту только в момент отключения питания - еще и ресурс EEPROM сэкономится. Все остальное время частота будет храниться в оперативной памяти процессора.

  3. Спасибо от DX888

  4. #3
    Цитата Сообщение от romanetz Посмотреть сообщение
    Попробуйте оставить конденсатор и диод по питанию проца и запоминать частоту только в момент отключения питания
    1. про конденсатор и диод я не понял... нужно что-то "ковырять" на DDS плате? DDS-ка у меня такая, в Китае брал готовый модуль https://ru.aliexpress.com/item/AD985...0-930c6a709864
    2. А как может частота запомниться, когда отключается питание?... там же нет своего резервного источника, ну, типа биоса...

  5. #4

    Регистрация
    28.04.2005
    Адрес
    Московская обл., г. Мытищи
    Сообщений
    3,923
    Позывной
    ex RW3DKC
    Ставите в разрыв питания ардуины диод и на само питания ардуины конденсатор от 470uF (лучше 1000) - этого хватит чтобы записать, наличие самого питания можно контролировать в основном цикле - с делителя внешнего (основного) питания заводите сигнал на любую входную ногу, пропал сигнал на этой ноге - пишите в eeprom. Лучше на прерывание завести, но тут занято энкодером.

    Послушал... хмм, это помеха такая при записи в EEPROM ? Нехило.

  6. Спасибо от DX888

  7. #5
    Цитата Сообщение от R2DHG Посмотреть сообщение
    этого хватит чтобы записать, наличие самого питания можно контролировать в основном цикле
    Наверное надо и уйти из основного цикла, иначе будет писать в ЕЕПРОМ все время, пока разрядится конденсатор.

  8. #6
    Ещё, в записи сильно слышны шорохи от кручения валкодера, насколько я понимаю. Проблема скорее c питанием, а не с кодом.
    В УНЧ "пролаз" сигналов c шин данных.

  9. #7

    Регистрация
    28.04.2005
    Адрес
    Московская обл., г. Мытищи
    Сообщений
    3,923
    Позывной
    ex RW3DKC
    Уж больно оно громко по сравнению с остальным, может и правда лучше не писать
    Цитата Сообщение от Владимир_К Посмотреть сообщение
    Наверное надо и уйти из основного цикла, иначе будет писать в ЕЕПРОМ все время, пока разрядится конденсатор.
    угу или флаг выставить чтобы это однократно происходило (или перед записью сверить не записано ли там уже такое же)

  10. #8
    Один раз записали и вернулись назад в программу. Если питание пропало совсем - стартуем потом сначала, если кратковременная пропажа питания и сброса не произошло - ничего страшного не случится. Побочный эффект: светодиоды на ноги процессора придется вешать только катодом к процессору. Т.к. вытекающий из портов ток берется от источника питания процессора, а втекающий - из источника питания периферии.

  11. #9
    Цитата Сообщение от R2DHG Посмотреть сообщение
    Ставите в разрыв питания ардуины диод и на само питания ардуины конденсатор от 470uF (лучше 1000) - этого хватит чтобы записать, наличие самого питания можно контролировать в основном цикле - с делителя внешнего (основного) питания заводите сигнал на любую входную ногу, пропал сигнал на этой ноге - пишите в eeprom. Лучше на прерывание завести, но тут занято энкодером.
    Полагаю, проблема не в этом. Скетч писался для ардуино ide и AD9850 чуть другой модификации. Писался автором в 13 году, а сейчас 17 год, уже и ардуино нано, и DDS 9850 чуть другая, может в этом и заключается проблема? Может всё же нужно просто код немного изменить?


  12. #10

    Регистрация
    28.04.2005
    Адрес
    Московская обл., г. Мытищи
    Сообщений
    3,923
    Позывной
    ex RW3DKC
    Код в storeMEM() никак не связан с синтезатором, возможно во время работы с EEPROM потребление тока увеличивается и помех по питанию больше становится. У вас модуль синтезатора запитан не от ардуины случайно ? Вот тут точно надо отдельно и через свои цепи развязки / стабилизаторы.

Страница 1 из 6 1234 ... ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Скомпилированная таблица частот на текущий момент
    от UA9ARM в разделе Правовой практикум радиолюбителя
    Ответов: 56
    Последнее сообщение: 06.11.2015, 18:43
  2. Ответов: 7
    Последнее сообщение: 27.12.2011, 15:29
  3. КВ синтезатор частоты с дискретным переключением частоты
    от user_199 в разделе Трансиверы, приемники КВ/УКВ
    Ответов: 8
    Последнее сообщение: 05.06.2011, 20:32
  4. Ответов: 61
    Последнее сообщение: 26.11.2009, 10:37

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •