Здравствуйте,
в программировании я полный нуб. пару дней пытался сделать сам, но дальше головной боли не продвинулся.
задача у меня такая:
собрал на Ардуино Нано и модуле 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();
}
}