デジタルが一応完成しましたが、さらに改良をくわえました。その2で開示したスケッチは変更しましたので、削除しました。
改良点
- 表示周波数のずれの補正は、バンドごとでしたが、モードによってキャリヤ周波数(水晶発振子)ことなりますので、ずれの値が異なります。よって、CWモードとUSB,LSBのそれぞれで補正し、メモリ格納し,表示する際にに加減算しますす。操作法は変更なく、現表示バンドモード・について記憶します。設定したのち、「Save」するか、電源offでEEPROMに転送します、
- すべての周波数、補正値を初期化できるようにしました。電源をOFFの状態で、「LOCK」SWを押すと,初期化します。表示周波数は下限になりますので、オフバンドに注意が必要です。
- Step 設定ですが、OFF→10Hz→100Hz→1kHz→10KH→→OFFとロータリー式に変化しますが、途中でStepSWをピッと鳴るまで長押しするとOFFになります。スケッチの変更部分は次の通りです。
/* changes the frequency change step */
/* 10Hz~1kHz まで,トグル動作 */
/* 長押しでOFF */
/*****************************************************/
void Fnc_Step()
{
int n = 0;
// 長押しでOFF
while( (digitalRead(SW_STEP) == LOW )){
if( Flag_Step == 1){
delay(100);
n++;
if(n > 10){
beep();
while( (digitalRead(SW_STEP) == LOW)){ ;
}
}
}
}
if (n >10){
step = 1;
Flag_Step = 0;
display_step();
}else{
step *= 10;
Flag_Step = 1;
if( step > 10000){
step = 1;
Flag_Step = 0;
}
delay(10);
display_step();
}
}
=2024/4/17 追記=
/******************************************************/
// Digtal_VFO_V4R0 T.Nakagawa 2024-02-525
// CPU : ATmega4809 / 328
//2024/3/20
// 1.V3.0を継承して、CPUを4089用との互換
// 2.バンド、モードのロータリーSWをやめて、プッシュSWによりソフトウエア処理。
//2024/3/22
// 3.Push SWによるアップダウン バンド切り替えと Mode切り替えOK。データメモリは[5]
// 4.4089を換装した。不具合がおおい。再コンパイル必要、
//24/3/23
// 5.3.5,7 bandはLSB,その他はUSBに自動設定。
//24/3/26
// 6. EEPROM アクセス方法簡素化EOPROM.put/get
//24/4/1 Ver 4.1
// 7.表示周波数補正、バンドのみならず、モードも対応
// 8.memory,EEPROM 初期化(Lock key )
// 9.
/*******************************************************/
#include <avr/sleep.h>
#include "Rotary.h"
#include "si5351.h"
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#define F_MIN 5000000L // Lower frequency limit
#define F_MAX 6500000L
#define DialLock 4 //Memory Return
#define SW_MW 5 //Memory Write
#define SW_MR 6 //Memory Read
#define SW_TX 7
#define SW_BAND_UP 8 //BAND 切り替えUP
#define SW_BAND_DWN 9 //BAND 切り替えDWN
#define SW_MODE 10 //MODE 切り替え
#define BZ 13 // beep
#define WakeUp 14 //A0 Wakeup
#define SW_STEP 15 //A1 ステップの切り替え
#define SW_RIT 16 //A2 Rit on/off
#define SleepMode 17 //A3 Sleep
/* ヘテロダイン周波数 */
#define Ht80 12395000L
#define Ht40 15895000L
#define Ht20 22895000L
#define Ht15 29895000L
#define Ht10 36895000L
/* キャリヤー周波数 */
#define CAR_CW 3395000L
#define CAR_USB 3396500L
#define CAR_SB 3393500L
/* PLL周波数レンジ (CW 時) */
#define Edg80Low 5425000L //3.575
#define Edg80Upr 5510000L //3.500
#define Edg40Low 5300000L //7.200
#define Edg40Upr 5510000L //7.000
#define Edg20Low 5150000L //14.350
#define Edg20Upr 5510000L //14.000
#define Edg15Low 5050000L //21.450
#define Edg15Upr 5510000L //212.00
#define Edg10Low 5000000L //28.500
#define Edg10Upr 5510000L //28.000
//const int EEPadd = 0; //EEPROM address
const int LOW_RIT = -990;
const int HI_RIT = +990;
// const Rotary Intr Pin
const int A_pin = 2;
const int B_pin = 3;
byte Flag_Rit = 0;
byte Flag_Tx = 0;
byte Flag_Step =0; // Step が on
byte Flag_DialLock =0; //
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7); // LCD 0x27:スレーブアドレス
/*2004:LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)*/
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
Si5351 si5351;
Rotary r = Rotary(A_pin,B_pin);
/* キャリヤー周波数廃列 */
volatile uint32_t Carrier[3] = {3395000L,3396500L,3393500L};
/* ヘテロダイン周波数廃列 */
volatile uint32_t HT[5] = {12395000L,15895000L,22895000L,29895000L,36895000L};
/* 標示VFO周波数廃列 CW時 */
volatile uint32_t LowVFO[5] = {5510000L,5510000L,5510000L,5510000L,5510000L};
volatile uint32_t ADJ[5][3]={0}; // 表示周波数の補正値[BandStat][ModeStat]
volatile uint32_t step = 1; // 1step の周波数(Hz)
String strMode = "USB"; // modo文字;
int RitFreq = 0;
int BandStat = 0; // 0,1,2,3,4 80m~10m
int ModeStat = 0; // 0,1,2 CW,SSB, LSB
/**************************************************************************************/
/* SetUp */
/**************************************************************************************/
void setup()
{
// Serial.begin(19200);
Serial.begin(9600);
lcd.setBacklightPin(3, POSITIVE);
lcd.setBacklight(LOW);
lcd.begin(20,4); // 表示のカラム×行
lcd.clear();
Wire.begin();
pinMode(A_pin, INPUT_PULLUP); // 2 RE A
pinMode(B_pin, INPUT_PULLUP); // 3 RE B
pinMode(DialLock, INPUT_PULLUP); // 4 D.LOCK
pinMode(SW_MW, INPUT_PULLUP); // 5 Save
pinMode(SW_MR, INPUT_PULLUP); // 6 Load
pinMode(SW_TX, INPUT_PULLUP); // 7 TX
pinMode(SW_BAND_UP, INPUT_PULLUP); // 8 Band SW
pinMode(SW_BAND_DWN, INPUT_PULLUP); // 9 Band SW
pinMode(SW_MODE, INPUT_PULLUP); // 10 Mode SW
pinMode(BZ, OUTPUT); // 13beep
pinMode(WakeUp, OUTPUT); // 14 A0 Wakeup;Relay on
pinMode(SW_STEP, INPUT_PULLUP); // 15 A1 step
pinMode(SW_RIT, INPUT_PULLUP); // 16 A2 Rit
pinMode(SleepMode, INPUT_PULLUP); // 17 A3 SleepMode
// 18 I2C SDA
// 19 I2C SCL
/*Start serial and initialize the Si5351*/
si5351.init(SI5351_CRYSTAL_LOAD_8PF);
/*Set CLK0 to output 5.5MHz with a fixed PLL frequency (VFO_DAT)*/
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
// vfo_dat= vfo; // 初期値をPLLデータへ
// si5351.set_freq(vfo_dat, SI5351_PLL_FIXED, SI5351_CLK0); // 24/2/4 CLK0へ変更
/*drive can be 2, 4, 6, or 8MA*/
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_6MA);
/*initialize interrupts on pins 2 and 3*/
attachInterrupt(digitalPinToInterrupt(A_pin), RotaryEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(B_pin), RotaryEncoder, CHANGE);
// attachInterrupt(digitalPinToInterrupt(SleepMode), SleepIntr,LOW); // only Every
digitalWrite(WakeUp,HIGH); // リレー ON
// memory ,EEPROM Initialoize
if ((digitalRead(DialLock) == LOW)){
initialize();
FreqDataWrite();
lcd.setCursor(18,2);
lcd.print("*_");
}
FreqDataRead(); // 電源 ON時,保存されたデーターを読み出す。
lcd.setCursor(1,0);
lcd.print("( )"); // Mode
display_mode(); // USB/LSB Mode Disp
lcd.setCursor(8,0);
lcd.print("-VFO- JA5ZZ"); //
lcd.setCursor(4,2);
lcd.print(" step ");
lcd.setCursor(12,2);
lcd.print(" rit "); //
lcd.setCursor(1,3);
lcd.print("__"); // TX
lcd.setCursor(15,1);
lcd.print("____"); // lock
beep();
sei();
}
/***************************************************/
/* Main program */
/***************************************************/
void loop()
{
/* 周波数表示 */
display_frequency (); // Frequency disp
/* ダイヤルロック*/
if ((digitalRead(DialLock) == LOW)){
Flag_DialLock = (Flag_DialLock ? 0 : 1);
lcd.setCursor(15,1);
if(Flag_DialLock ==1){
lcd.print("lock");
}else{
lcd.print("____");
}
beep();
while(digitalRead(DialLock) == LOW){
delay(10);
}
}
/* Sleep,Power Down処理*/
if (digitalRead(SleepMode) == LOW){
beep();
PowerDown();
}
/* STEP 設定*/
if (digitalRead(SW_STEP) == LOW) {
beep();
Fnc_Step();
}
/* RIT 設定*/
if (digitalRead(SW_RIT) == LOW) {
beep();
Fnc_Rit();
}
Fnc_Rit_Disp();
/* EPROMへセーブ */
if (digitalRead(SW_MW) == LOW) {
beep();
if (digitalRead(SW_MW) == LOW){
FreqDataWrite();
}
while(digitalRead(SW_MW) == LOW){
delay(10);
}
}
/* EPROMからロード */
if (digitalRead(SW_MR) == LOW) {
beep();
if(digitalRead(SW_MR)== LOW){
FreqDataRead();
}
while(digitalRead(SW_MR) == LOW){
delay(10);
}
}
/* 送信チェック */
if (digitalRead(SW_TX) == LOW){
delay(10);
Flag_Tx = 1;
lcd.setCursor(1,3);
lcd.print("TX");
delay(10);
while(digitalRead(SW_TX) == LOW){
}
}else{
Flag_Tx = 0;
lcd.setCursor(1,3);
lcd.print("__");
}
/* PLL Freq data set */
Fnc_Dds();
/* Band UP SW */
if (digitalRead(SW_BAND_UP) == LOW) {
beep();
Fnc_Band_UP();
}
/* Band DWN SW */
if (digitalRead(SW_BAND_DWN) == LOW) {
beep();
Fnc_Band_DWN();
}
/* Mode SW */
if (digitalRead(SW_MODE) == LOW){
beep();
Fnc_Mode(); // USB/LSB Mode Dis
}
}
/**********************************************************/
/* Power \down Sleep */
/* Freq Data ,BandStat,ModeSTatを EEPROM に退避する */
/**********************************************************/
void PowerDown()
{
/* 割り込み要因 SleepMode not use */
sleep_enable();
FreqDataWrite();
delay(100);
lcd.noDisplay();
lcd.noBacklight();
digitalWrite(WakeUp,LOW); // 電源リレー OFF 以下は実行されない
sleep_cpu();
while (1){
;
}
}
/**********************************************************/
/* 周波数データ EPROM からロード */
/* 4byte(long値)× 5 Field ×2 Recode + 2Byte */
/**********************************************************/
void FreqDataRead()
{
//VFO 周波数 load
for(int n=0;n<5;n++){
EEPROM.get(n *4,LowVFO[n]);
}
//ADJ値Load
int adr=20;
for(int n=0;n<5;n++){
for(int m=0; m<3; m++){
EEPROM.get(adr,ADJ[n][m]);
adr +=4;
}
}
// BandStat & ModeStat Load 1byte
BandStat = EEPROM.read(60);
ModeStat = EEPROM.read(61);
lcd.setCursor(18,3);
lcd.print("*L");
}
/**********************************************************/
/* 周波数データ EPROM へセーブ */
/* 4byte(long値)× 5 Field ×2 Recode + 2byte */
/**********************************************************/
void FreqDataWrite()
{
// 周波数データ save
for(int n=0;n<5;n++){
EEPROM.put(n *4,LowVFO[n]);
}
//ADJ値Save Each Baand & Mode
int adr=20;
for(int n=0;n<5;n++){
for(int m=0;m<3;m++){
EEPROM.put(adr,ADJ[n][m]);
adr +=4; // adr (20+n*4+m*4) NG ?
};
}
// BandStat & ModeStat Save 1byte
EEPROM.write(60, BandStat);
EEPROM.write(61, ModeStat);
lcd.setCursor(18,2);
lcd.print("*S");
}
/**********************************************************/
/* Interrupt service routine for encoder */
/* frequency change ISR(PCINT2_vect) */
/**********************************************************/
void RotaryEncoder()
{
unsigned char result = r.process();
if (!Flag_DialLock && !Flag_Tx){
if (result == DIR_CW) { // 右回り 増加
if ((Flag_Rit == 1) && (digitalRead(SW_TX) == HIGH)) {
RitFreq = RitFreq - 1;
} else {
if (Flag_Step){
LowVFO[BandStat] = LowVFO[BandStat]-step;
}else{
LowVFO[BandStat] = LowVFO[BandStat]-1;
}
}
} else {
if (result == DIR_CCW) { // 左回り 減
if ((Flag_Rit == 1) && (digitalRead(SW_TX) == HIGH)) {
RitFreq = RitFreq + 1;
} else {
if (Flag_Step){
LowVFO[BandStat] = LowVFO[BandStat] + step;
}else{
LowVFO[BandStat] = LowVFO[BandStat] +1;
}
}
}
}
RitFreq = constrain(RitFreq, LOW_RIT, HI_RIT);
LowVFO[BandStat] = constrain(LowVFO[BandStat], 4900000L, 5510000L);
}
}
/**********************************************************/
/* Displays the frequency */
/* local memory 32Bit */
/**********************************************************/
void display_frequency()
{
uint32_t f, f1, f2,f3,f4;
char buff[6];
// テロダインf-(vfo+キャリヤー) = 送受信周波数、表示周波数はADJで補正
f = (HT[BandStat] - LowVFO[BandStat] - Carrier[ModeStat]) +( ADJ[BandStat][ModeStat]);
// Serial.println(ADJ[BandStat][ModeStat]);
// Serial.println(f);
f1 = f / 1000000; //**MHz
f2 = f % 1000000;
f3 = f2 / 1000; //f3=***kHz
f4 = f2 % 1000; //f4=***Hz
// LCD表示
lcd.setCursor(1,1);
sprintf(buff,"%2d,",f1);
lcd.print(buff);
sprintf(buff,"%03d,",f3);
lcd.print(buff);
sprintf(buff,"%03dHz",f4);
lcd.print(buff);
}
/**********************************************************/
/* changes the frequency change step */
/* 10Hz~1kHz まで,トグル動作 */
/**********************************************************/
void Fnc_Step()
{
step *= 10;
Flag_Step =-1;
if( step > 10000){
step = 1;
Flag_Step = 0;
}
delay(10);
display_step();
while (digitalRead(SW_STEP) == LOW) {
delay(10);
}
}
/**********************************************************/
/* changes the Band UP */
/* 80m~10m まで,トグル動作 */
/**********************************************************/
void Fnc_Band_UP()
{
if( (BandStat += 1) >4){
BandStat = 0;
}
if(BandStat == 0 || BandStat ==1){
ModeStat = 2; // LSB
}else{
ModeStat = 1; // USB
}
while (digitalRead(SW_BAND_UP) == LOW) {
delay(10);
}
display_frequency();
display_mode(); // USB/LSB Mode Dis
}
/**********************************************************/
/* changes the Band Down */
/* 80m~10m まで,トグル動作 */
/**********************************************************/
void Fnc_Band_DWN()
{
if( (BandStat -= 1) < 0){
BandStat = 4;
}
if(BandStat == 0 || BandStat ==1){
ModeStat = 2; // LSB
}else{
ModeStat = 1; // USB
}
while (digitalRead(SW_BAND_DWN) == LOW) {
delay(10);
}
display_frequency();
display_mode(); // USB/LSB Mode Dis +
}
/**********************************************************/
/* changes the Mode */
/* CW,USB, LSB まで,トグル動作 */
/**********************************************************/
void Fnc_Mode()
{
ModeStat += 1;
if( ModeStat > 2){
ModeStat = 0;
}
while (digitalRead(SW_MODE) == LOW) {
delay(10);
}
display_mode(); // USB/LSB Mode Dis
}
/**********************************************************/
/* Step 周波数表示 */
/* Displays the frequency change step */
/**********************************************************/
void display_step()
{
char strStep[8] ;
switch (step) {
case 1:
sprintf(strStep," ");
break;
case 10: // 10Hz
sprintf(strStep,"%4dHz",step);
break;
case 100: // 100Hz
sprintf(strStep,"%4dHz",step);
break;
case 1000: // 1kHz
sprintf(strStep,"%3dkHz",step/1000);
break;
case 10000: // 10kHz
sprintf(strStep,"%3dkHz",step/1000);
break;
}
lcd.setCursor(4, 3);
lcd.print(strStep);
}
/**********************************************************/
/* RIT 設定 */
/* RIT */
/**********************************************************/
void Fnc_Rit()
{
if (Flag_Rit == 1) {
Flag_Rit = 0;
} else {
Flag_Rit = 1;
}
delay(10);
Fnc_Rit_Disp();
while (digitalRead(SW_RIT) == LOW) {
delay(10);
}
}
/**********************************************************/
/* RIT 表示 & 周波数補正 */
/* Rit_Disp & */
/**********************************************************/
void Fnc_Rit_Disp()
{
int n=0;
char Rit_F[8];
if (Flag_Rit == 1) {
sprintf(Rit_F,"%4dHz", RitFreq*-1);
} else {
// 長押しで補正 adj
while( (digitalRead(SW_RIT) == LOW)){
delay(100);
n++;
if(n > 10){
beep();
while( (digitalRead(SW_RIT) == LOW)){ ;
}
}
}
if (n >10){
RitFreq =RitFreq*-1;
ADJ[BandStat][ModeStat] += RitFreq;
} else {
sprintf(Rit_F,"%s"," " );
RitFreq = 0;
}
}
lcd.setCursor(12,3);
lcd.print(Rit_F);
}
/**********************************************************/
/* Dds out */
/* Rit on RX時のみ加算する。step は RE intraで加算されている */
/**********************************************************/
void Fnc_Dds()
{
uint32_t n = 0;
if (!Flag_Rit && !Flag_Tx){
si5351.set_freq(LowVFO[BandStat], SI5351_PLL_FIXED, SI5351_CLK0);
n=LowVFO[BandStat];
}else{
si5351.set_freq((LowVFO[BandStat])+ RitFreq, SI5351_PLL_FIXED, SI5351_CLK0);
n=LowVFO[BandStat]+RitFreq;
}
// Serial.println(n);
}
/**********************************************************/
/* Mode_Display */
/**********************************************************/
void display_mode()
{
switch (ModeStat){
case 0:
strMode = "CW ";
break;
case 1:
strMode = "USB";
break;
case 2:
strMode = "LSB";
break;
default:
break;
}
lcd.setCursor(2, 0);
lcd.print(strMode);
}
/**********************************************************/
/* beep */
/**********************************************************/
void beep()
{
digitalWrite(BZ,HIGH);
delay(10);
digitalWrite(BZ,LOW);
}
/**********************************************************/
/* memori イニシャライズ */
/**********************************************************/
void initialize()
{
// 周波数データ
for(int n=0;n<5;n++){
LowVFO[n]= 5510000L;
}
//ADJ値
for(int n=0;n<5;n++){
for(int m=0;m<3;m++){
ADJ [n][m]=0L;
}
}
// BandStat & ModeStat
BandStat=0;
ModeStat=0;
}
/********************** end of Program ***********************/