Прошу помочь с Si5351

Здравствуйте,
в программировании я полный нуб. пару дней пытался сделать сам, но дальше головной боли не продвинулся.
задача у меня такая:
собрал на Ардуино Нано и модуле si5351 синтезатор для радиолюбительского приемника. Пробовал несколько разных скетчей, в итоге нашел один более-менее мне подходящий. Как сумел, переделал его под мои задачи (для приема Авиа диапазона, в т.ч.). Однако, сейчас потестил этот синтезатор + самодельный блок КВ приемника и услышал, что на КВ он очень хорошо работает (много станций, в т.ч. на СВ и несколько на длинных волнах). Вспомнил, что у si5351 есть возможность вывести опорный генератор. Включил его в скетче (CLK_2), подключил к ПЧ смесителю и приемник стал принимать SSB сигналы (радиолюбителей).
Однако, возникла необходимость вкл/выкл этот выход CLK_2, для того, чтобы переключаться между двумя модуляциями: АМ и SSB.
С этим вкл/выкл с помощью простой кнопки и вышел у меня затык. Полагаю, что самому мне не справится. Поэтому прошу помочь.
Задача: вкл/выкл CLK_2 с помощью кнопки (подтянута резистором к + питания) и, параллельно, отображать на дисплее какая именно модуляция включена: АМ или SSB
код:

#include <Rotary.h>
#include <si5351.h>
#include "Wire.h"
#include <LiquidCrystal.h>

//#define OLED_RESET 4
#define ENCODER_A 5  // Encoder pin A
#define ENCODER_B 4  // Encoder pin B
#define ENCODER_BTN 3
#define SSB_AM 2  // Select SSB or AM
//#define LCD_RS		5
//#define LCD_E		  6
//#define LCD_D4		7
//#define LCD_D5		8
//#define LCD_D6		9
//#define LCD_D7		10

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);  // LCD - pin assignement in
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);

volatile uint64_t frequency0 = 125e8 / SI5351_FREQ_MULT;  //10Mhz - change to suit your needs
//just take care to count the right number of zeros.
//  volatile uint32_t frequency1 = 9000000L;
//  volatile uint32_t frequency2 = 10000000L;
volatile uint64_t radix = 1e6;
boolean changed_f = 0;



/**************************************/
/* Interrupt service routine for      */
/* encoder frequency change           */
/**************************************/
//ENCODER_A.pinMode (1);
//ENCODER_B.pinMode (1);

ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result == DIR_CW)
    set_frequency(1);
  else if (result == DIR_CCW)
    set_frequency(-1);
}
/**************************************/
/* Change the frequency               */
/* dir = 1    Increment               */
/* dir = -1   Decrement               */
/**************************************/
void set_frequency(short dir) {
  if (dir == 1)
    frequency0 += radix;
  if (dir == -1)
    frequency0 -= radix;
  changed_f = 1;
}
/**************************************/
/* Read the button with debouncing    */
/**************************************/
boolean get_button(byte btn_num) {
  if (!digitalRead(ENCODER_BTN)) {
    delay(20);
    if (!digitalRead(ENCODER_BTN)) {
      while (!digitalRead(ENCODER_BTN))
        ;
      return 1;
    }
  }
  if (!digitalRead(SSB_AM)) {
    delay(20);
    if (!digitalRead(SSB_AM)) {
      while (!digitalRead(SSB_AM))
        ;
      return 1;
    }
  }
  return 0;
}

/**************************************/
/* Displays the frequency             */
/**************************************/
void display_frequency() {
  uint16_t f, g;

  lcd.setCursor(1, 1);
  f = frequency0 / 1000000;
  if (f < 10)
    lcd.print(' ');
  lcd.print(f);
  lcd.print('.');
  f = (frequency0 % 1000000) / 1000;
  if (f < 100)
    lcd.print('0');
  if (f < 10)
    lcd.print('0');
  lcd.print(f);
  lcd.print('.');
  f = frequency0 % 1000;
  if (f < 100)
    lcd.print('0');
  //if(f<10)
  //lcd.print('0');
  //lcd.print('0');
  lcd.print(f);
  //lcd.print("Hz");
}

/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix() {
  lcd.setCursor(9, 0);
  switch (radix) {
    case 10:
      lcd.print("   10");
      break;
    case 100:
      lcd.print("  100");
      break;
    case 1000:
      //lcd.setCursor(9, 0);
      lcd.print("   1k");
      break;
    case 10000:
      lcd.print("  10k");
      break;
    case 100000:
      lcd.print(" 100k");
      break;
    case 1000000:
      lcd.setCursor(9, 0);
      lcd.print("   1M");  //1MHz increments
      break;
  }
  lcd.print("");
}

unsigned long int current_freq;


void setup() {


  pinMode(2, OUTPUT);

  lcd.begin(16, 2);  // Initialize and clear the LCD
  lcd.clear();
  lcd.noBlink();
  lcd.setCursor(0, 1);
  lcd.print(" Klepa & Krokik");
  lcd.setCursor(0, 0);
  lcd.print("     Hello");
  delay(2000);
  lcd.clear();





  Wire.begin();
  // Start serial and initialize the Si5351 with load capacitance and crystal freq
  //0 will provide default freq of 25Mhz. If you have a 27MHz crystal put in 27000000
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);  //you could measure your crystal and put it here to correct for errors.
                                               // Set CLK0 to output 10 MHz with a fixed PLL frequency
  si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA);
  si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_2MA);
  si5351.output_enable(SI5351_CLK0, 1);
  si5351.output_enable(SI5351_CLK2, 1);
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
  //set frequency with 1 Hz resolution
  si5351.set_freq(45500000, SI5351_CLK2);
  si5351.set_freq(frequency0 * 100, SI5351_CLK0);
  //si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_6MA);
  pinMode(ENCODER_A, INPUT_PULLUP);
  pinMode(ENCODER_B, INPUT_PULLUP);
  pinMode(ENCODER_BTN, INPUT_PULLUP);

  PCICR |= (1 << PCIE2);  // Enable pin change interrupt for the encoder
  PCMSK2 |= (1 << PCINT20) | (1 << PCINT21);
  sei();
  changed_f = 1;        //added to initialize si5351
  display_frequency();  // Update the display
  display_radix();
}


void loop() {
  // Update the display if the frequency has been changed
  if (changed_f) {
    display_frequency();
    si5351.set_freq((frequency0 * 100 + 45300000), SI5351_CLK0);  // вычитание или сложение ПЧ
    changed_f = 0;
  }

  // Button press changes the frequency change step
  //if(get_button(2))
  //{

  //else if (SI5351_CLK0 == 1) vfo_act1 ^= 1;            // если CLK1 = ON то OFF
  //else if (SI5351_CLK0 == 0) vfo_act0 = vfo_act1 ^= 1; // если CLK0,CLK1 = ON то OFF
  //if si5351.output_enable(SI5351_CLK2, 1); else si5351.output_enable(SI5351_CLK2, 0);
  //if si5351.output_enable(SI5351_CLK2, 0); else si5351.output_enable(SI5351_CLK2, 1);
  //}

  if (get_button(3)) {
    switch (radix) {
      case 10:
        radix = 100;
        break;
      case 100:
        radix = 1000;
        break;
      case 1000:
        radix = 10000;
        break;
      case 10000:
        radix = 100000;
        break;
      case 100000:  //change these lines to tune in 1MHz increments
        radix = 1000000;
        break;
      case 1000000:
        radix = 10;
        break;
    }
    display_radix();
  }
}

А в чём затык-то? Что не получилось? Не вижу в коде Вашей попытки, подскажите где она (номера строк).

строка 10: подключил кнопку к пину 2 Ардуино нано
строка 69 опрос кнопки
197 строка и ниже - моя кривая попытка сделать то, что задумал
я, как уже говорил, полный нуб в этом.

Тьфу ты… Я то думал нужны байты. Вот из какой-то из библиотек:

si5351.si5351_write(18, 0x0c);              // включаем выход CLK2
si5351.si5351_write(18, 0x80);              // выключаем выход CLK2

Ну что поделать - никто не идеален. Учись нуб ))

Для решения твоей задачи нужно (алгоритм):

  1. Завести булеву переменную - флаг. Она будет сигнализировать о том нужно включать CLK2 или выключать.
  2. Далее прочитать кнопку
  3. Если кнопка была нажата - инвертируем значение переменной флага на противоположное
  4. В программе “смотрим” на переменную-флаг, и если она в значении true - включаем CLK2 и отображаем значек на дисплее. Если она в значении false - выключаем CLK2 и стрием значек (или меняем - тут по желанию).
  5. Алгоритм завершен.

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

…что такое алгоритм … ? Куда намазать ?

Мажь на хлеб )))

Алгоритм — это четкая последовательность действий, выполнение которой дает какой-то заранее известный результат. Простыми словами, это набор инструкций для решения конкретной задачи.

спасибо за ответ
вы могли бы намекнуть, как соединить переменную-“флаг” и выход CLK_2 блока si5351? через int сейчас пробую, но, похоже, совсем не то делаю…

Извините, но это бредовая фраза. Флаг - это просто переменная

bool flag = false;

Причем, имя flag - это просто пример, оно может быть разным. Проверка значения флага

if(flag == true)
{
// здесь делаете то, что должно происходить при flag == true
}
else
{
// здесь делаете то, что должно происходить при flag == false
}

Но форум - не место для обучения, прочтите хотя бы один учебник по языку

я не способен научиться программированию. такова моя особенность.

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

bool SI5351_clock_2 = false 
  if(SI5351_clock_2 == true)
  {
  lcd.setCursor(0, 1);
  lcd.print("SSB"); // здесь делаете то, что должно происходить при flag == true
  }
  else
  {
  lcd.setCursor(0, 1);
  lcd.print("AM");// здесь делаете то, что должно происходить при flag == false
  }

Тогда что вы тут делаете? Заказывайте код тому, кто в этом разбирается

в конце первой строки не хватает ;

Толку то? Кнопку то он не читает и состояние не меняет ))

зато скомпилируется, я тока об этом))

большое спасибо за помощь
сделаю на реле и тумблере.

так бы наверное и сделал, будь не 17 рублей 50 копеек в кармане.

Тог8да Вам на этом форуме делать нечего.
Этот форум - клуб по интересам. Вы общих интересов не разделяете. Зачем Вы здесь?

извините, что посмел себе позволить зайти сюда.

сделал. работает


#include <Rotary.h>
#include <si5351.h>
#include "Wire.h"
#include <LiquidCrystal.h>

//#define OLED_RESET 4
#define ENCODER_A 5  // Encoder pin A
#define ENCODER_B 4  // Encoder pin B
#define ENCODER_BTN 3
#define SSB_AM 2  // Select SSB or AM
//#define LCD_RS		5
//#define LCD_E		  6
//#define LCD_D4		7
//#define LCD_D5		8
//#define LCD_D6		9
//#define LCD_D7		10

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);  // LCD - pin assignement in
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);

volatile uint64_t frequency0 = 125e8 / SI5351_FREQ_MULT;  //10Mhz - change to suit your needs
//just take care to count the right number of zeros.
//  volatile uint32_t frequency1 = 9000000L;
//  volatile uint32_t frequency2 = 10000000L;
volatile uint64_t radix = 1e6;
boolean changed_f = 0;



/**************************************/
/* Interrupt service routine for      */
/* encoder frequency change           */
/**************************************/
//ENCODER_A.pinMode (1);
//ENCODER_B.pinMode (1);

ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result == DIR_CW)
    set_frequency(1);
  else if (result == DIR_CCW)
    set_frequency(-1);
}
/**************************************/
/* Change the frequency               */
/* dir = 1    Increment               */
/* dir = -1   Decrement               */
/**************************************/
void set_frequency(short dir) {
  if (dir == 1)
    frequency0 += radix;
  if (dir == -1)
    frequency0 -= radix;
  changed_f = 1;
}
/**************************************/
/* Read the button with debouncing    */
/**************************************/
boolean get_button(byte btn_num) {
  if (!digitalRead(ENCODER_BTN)) {
    delay(50);
    if (!digitalRead(ENCODER_BTN)) {
      while (!digitalRead(ENCODER_BTN));
      return 1;
    }
  }
  return 0;
}

//boolean get_button1(byte btn_num) {
  //if (!digitalRead(SSB_AM)) {
    //delay(20);
    //if (!digitalRead(SSB_AM)) {
      //while (!digitalRead(SSB_AM));
      //return 1;
    //}
  //}
  //return 0;
//}


/**************************************/
/* Displays the frequency             */
/**************************************/
void display_frequency() {
  uint16_t f, g;

  lcd.setCursor(1, 1);
  f = frequency0 / 1000000;
  if (f < 10)
    lcd.print(' ');
  lcd.print(f);
  lcd.print('.');
  f = (frequency0 % 1000000) / 1000;
  if (f < 100)
    lcd.print('0');
  if (f < 10)
    lcd.print('0');
  lcd.print(f);
  lcd.print('.');
  f = frequency0 % 1000;
  if (f < 100)
    lcd.print('0');
  //if(f<10)
  //lcd.print('0');
  //lcd.print('0');
  lcd.print(f);
  //lcd.print("Hz");
}

/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix() {
  lcd.setCursor(9, 0);
  switch (radix) {
    case 10:
      lcd.print("   10");
      break;
    case 100:
      lcd.print("  100");
      break;
    case 1000:
      //lcd.setCursor(9, 0);
      lcd.print("   1k");
      break;
    case 10000:
      lcd.print("  10k");
      break;
    case 100000:
      lcd.print(" 100k");
      break;
    case 1000000:
      lcd.setCursor(9, 0);
      lcd.print("   1M");  //1MHz increments
      break;
  }
  lcd.print("");
}

unsigned long int current_freq;

void setup() 
{
  lcd.begin(16, 2);  // Initialize and clear the LCD
  lcd.clear();
  lcd.noBlink();
  lcd.setCursor(0, 1);
  lcd.print(" Klepa & Krokik");
  lcd.setCursor(0, 0);
  lcd.print("     Hello");
  delay(2000);
  lcd.clear();

  
    Wire.begin();
  // Start serial and initialize the Si5351 with load capacitance and crystal freq
  //0 will provide default freq of 25Mhz. If you have a 27MHz crystal put in 27000000
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);  //you could measure your crystal and put it here to correct for errors.
                                               // Set CLK0 to output 10 MHz with a fixed PLL frequency
  //si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA);
  //si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_2MA);
  si5351.output_enable(SI5351_CLK0, 1);

  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
  //set frequency with 1 Hz resolution
  si5351.set_freq(45500000, SI5351_CLK2);
  si5351.set_freq(frequency0 * 100, SI5351_CLK0);
  si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_4MA);
  si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_2MA);
  pinMode(ENCODER_A, INPUT_PULLUP);
  pinMode(ENCODER_B, INPUT_PULLUP);
  pinMode(ENCODER_BTN, INPUT_PULLUP);
  pinMode(SSB_AM, INPUT_PULLUP);
  PCICR |= (1 << PCIE2);  // Enable pin change interrupt for the encoder
  PCMSK2 |= (1 << PCINT20) | (1 << PCINT21);
  sei();
  changed_f = 1;        //added to initialize si5351
  display_frequency();  // Update the display
  display_radix();
}


int A = 0;
int regim=1;

void loop() {
  // Update the display if the frequency has been changed
  if (changed_f) {
    display_frequency();
    si5351.set_freq((frequency0 * 100 + 45300000), SI5351_CLK0);  // вычитание или сложение ПЧ
    changed_f = 0;
  }
 
    
 // код для перекл. взял отсюда: https://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku
  if(digitalRead(2)==HIGH&&A==0) 
     { 
       regim++;   
       A=1; 
        if(regim>2)//кол-во режимов 
        { 
        regim=1;
        }        
     } 
     ///  
      if(digitalRead(2)==LOW&&A==1)
     { 
      A=0;
     } 
    ///  
    if(regim==1)//первый режим 
    { 
      si5351.output_enable(SI5351_CLK2, 1);
      lcd.setCursor(1, 0);
      lcd.print("SSB"); 
    } 
    ///
    if(regim==2)//второй режим 
    { 
      si5351.output_enable(SI5351_CLK2, 0); 
      lcd.setCursor(1, 0);
      lcd.print(" AM");       
    } 
      
    //if(regim==3)//третий режим 
    //{ 
        
      //si5351.output_enable(SI5351_CLK2, 0); 
      //lcd.setCursor(1, 0);
      //lcd.print(" FM");  
    //} 
    
    //if(regim==4)//четвертый режим 
    //{ 
         //действие 
    //}
      
          
 

  // Button press changes the frequency change step
 
  if (get_button(3)) {
    switch (radix) {
      case 10:
        radix = 100;
        break;
      case 100:
        radix = 1000;
        break;
      case 1000:
        radix = 10000;
        break;
      case 10000:
        radix = 100000;
        break;
      case 100000:  //change these lines to tune in 1MHz increments
        radix = 1000000;
        break;
      case 1000000:
        radix = 10;
        break;
    }
    display_radix();
  }
}

А подтяжку сменил с VCC на GND?