2017年7月31日月曜日

K4GC VFO

何時もお世話になっているKさんから、K4GC VFOスケッチについて相談を受けた。エンコーダ操作で周波数調整が困難との事であった。スケッチを見ると割込み処理を行わずに、エンコーダ読取りが行われており、取りこぼしが原因と思われる。今回問題が有ったエンコーダ処理とLCD表示を変更した。

回路図である。
ダイレクトコンバージョン受信機と組合わせた40m CW QRP機で、フルブレイクイン動作する。オリジナルからkey paddleとエンコーダのIO割付のみ変更。









スケッチ

基本的な処理は、オリジナルを継承している。RIT処理がアナログ処理で行われており、参考になる所もある。スケッチは、ダウンロードサイトのsi5351aフォルダ。

/**************************************************************************
   DIRECT CONVERSION CW TRANSCEIVER CONTROLLER WITH IAMBIC KEYER FOR ARDUINO
   Uses SI5351 clock generator shild from Adafruit for VFO
   Uses NT7S SI5351 library for Arduino on github:
   https://github.com/etherkit/Si5351Arduino
   2 x 16 LCD display for frequency, offset, and tuning rate
   Has an iambic keyer with dot/dash memories
   Arduino Pro Mini pin assignments:
   2) Encoder A input
   3) Encoder B input
   4) STEP SW
   5) Iambic paddle DSH input
   6) Iambic paddle DIT input
   7)
   8) Transmit/mute output
   9) Sidetone output
   10) LCD RS output
   11) LCD E output
   12) LCD D4 output
   13) LCD D5 output
   A0) LCD D6 output
   A1) LCD D7 output
   A2)
   A3)
   A4) si5351 SDA
   A5) si5351 SCL
   A6) Offset voltage input
   A7) Keyer speed voltage input
 ***************************************************************************/

#include <si5351.h>
#include "Wire.h"
#include <Rotary.h>
#include "src/LiquidCrystal.h"                // use Arduino LCD library.


//----------   PLL setting  --------------------

Si5351 si5351;

//----------   LCD setting  --------------------

LiquidCrystal lcd(10, 11, 12, 13, A0, A1);  // RS,E,D4,D5,D6,D7

//----------   Encorder setting  ---------------

#define   ENC_A       2                       // Encorder A
#define   ENC_B       3                       // Encoeder B

Rotary r=Rotary(ENC_A,ENC_B);


////////////////////////ENCODER SETUP///////////////////////////////////////
#define SW_STEP       4
#define Pad_Dah       5
#define Pad_Dit       6  
#define XMIT          8
#define TONE          9

#define LW_FRQ        7000000L
#define HI_FRQ        7200000L

long Vfo_Dat = 7030000L;                      //Start up frequency <<<2017/6/27>>>
long Vfo_Datb = 0;                            //                   <<<2017/6/27>>>
int Enc_Stp = 10;                             // STEP=10Hz
int rateindicator = 5;
char Lcd_data[17] = "                ";
int Flg_Set0 = 1;
/////////////////////////////////////////////////////////////////////////////

//////////////////////////////RIT SETUP//////////////////////////////////////
int rit = A6;
int ritvoltage = 0;
int oldritvoltage = 0;
int modulo = 0;
int ritcenter = 512;
int rittune = 0;
int rittuneb = rittune;
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////IAMBIC KEYER////////////////////////////////////
int count = 0;
int dit = 1;
int dah = 1;
int sidetone = 700;
int ditmem = 0;
int dahmem = 0;
int sspeed = 50;
int speedinput = A7;
/////////////////////////////////////////////////////////////////////////////

//----------  Setup  ---------------

void setup(){
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);
  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
  lcd.begin(16, 2);

  pinMode(Pad_Dah, INPUT_PULLUP);                  // Dah
  pinMode(Pad_Dit, INPUT_PULLUP);                  // Dit

  pinMode(SW_STEP, INPUT_PULLUP);                  // STEP

  pinMode(TONE, OUTPUT);
  pinMode(XMIT, OUTPUT);
  digitalWrite(XMIT, HIGH);

  PCICR |=(1<<PCIE2);
  PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
  sei();

  Fnc_Step_Disp();
}

//----------  Main loop  --------

void loop() {
  if(digitalRead(SW_STEP) == LOW)                   // STEP SW On?
    Fnc_Stp();                          

  setclock0();
 
  ritvoltage = analogRead(A6);
  rittune = ritvoltage - ritcenter;
  rittune = rittune * 5;
  if (ritvoltage != oldritvoltage){
    ritune();
  }

  if (ditmem == 1) makedit();
  if (dahmem == 1) makedah();
  sspeed = analogRead(speedinput);
  sspeed = sspeed / 6.5;
  if (sspeed < 24) sspeed = 24;
  count = 0;
  checkpaddle();
}

//----------  Encorder procedure(INT)  ---------------

ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if(result) {  
    if(result == DIR_CW)
      Vfo_Dat = Vfo_Dat + Enc_Stp;
    else
      Vfo_Dat = Vfo_Dat - Enc_Stp;
    Vfo_Dat = constrain(Vfo_Dat,LW_FRQ,HI_FRQ);
  }
  Flg_Set0 = 1;
}

//----------  Set Clock0  ---------------

void setclock0() {                            //function to set the SI5351 clock frequency
  if(Flg_Set0 == 1){
    lcd.setCursor(2, 0);
    Fnc_Dot_Edit(Lcd_data,Vfo_Dat);
    lcd.print(Lcd_data);
    lcd.print(" MHz");
    si5351.set_freq((Vfo_Dat + rittune) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
  }
  Flg_Set0 = 0;
}

//----------  RIT proc  ---------------

void ritune() {                             //function to determine RIT offset frequency
  modulo = 0;
  oldritvoltage = ritvoltage;
  rittune = ritvoltage - ritcenter;
  rittune = rittune * 5;                    //RIT steps in 5 Hz increments
  if (rittune > 30) {                       //Keep a dead zone near 0 offset
    rittune = rittune;
  }
  else if (rittune < -30)  {
    rittune = rittune;                      //Keep a dead zone near 0 offset
  }
  else {
    rittune = 0;
  }
  lcd.setCursor(8, 1);
  lcd.print("        ");
  lcd.setCursor(8, 1);
  lcd.print("Rit");
  if (rittune > 0) {
    lcd.print("+");
  }
  lcd.print(rittune);
  Flg_Set0 = 1;
  setclock0();
}

//----------  Check Paddle  ---------------

void checkpaddle() {                            //function for checking iambic paddle status
  dit = digitalRead(Pad_Dit);
  dah = digitalRead(Pad_Dah);
  if (!dit) makedit();
  if (!dah) makedah();
}

//----------  Dit make proc  ---------------

void makedit() {                                //function to make dits
  count = 0;
  ditmem = 0;
  si5351.set_freq(Vfo_Dat * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
  digitalWrite(XMIT, 0);
  tone(TONE, sidetone);
  while (count < sspeed) {
    dah = digitalRead(Pad_Dah);
    if (!dah) dahmem = 1;
    delay(1);
    ++count;
  }
  count = 0;
  noTone(TONE);
  digitalWrite(XMIT, 1);
  si5351.set_freq((Vfo_Dat + rittune) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
    while (count < sspeed) {
    dah = digitalRead(Pad_Dah);
    delay(1);
    ++count;
  }
}

//----------  Dah make proc  ---------------

void makedah(){                                 //function to make dahs
  count = 0;
  dahmem = 0;
  si5351.set_freq(Vfo_Dat * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);
  digitalWrite(XMIT, 0);
  tone(TONE, sidetone);

  while (count < (sspeed * 3)){
    dit = digitalRead(Pad_Dit);
    if (!dit) ditmem = 1;
    delay(1);
    ++count;
  }

  count = 0;
  noTone(TONE);
  digitalWrite(XMIT, 1);
  si5351.set_freq((Vfo_Dat + rittune) * SI5351_FREQ_MULT, SI5351_PLL_FIXED, SI5351_CLK0);

  while (count < sspeed) {
    dit = digitalRead(Pad_Dit);
    if (!dit) ditmem = 1;
    delay(1);
    ++count;
  }
}

//----------  Function String Dot Edit  --------
 
char *Fnc_Dot_Edit(char *str,long n){
  int  i = 0;                           // Write the number
  char *p = str;
  unsigned long  u = abs(n);

  do{
    *p++ = "0123456789"[u % 10];
    u = u / 10;
    i++;
    if((0 != u) && (0 == (i % 3)))
      *p++ = '.';
    }
  while( 0 != u );

  if ( n < 0 )
     *p++ = '-';
   *p = '\0';
   Fnc_Revr( str );
   return str;
}

//----------  Function String Reverse  ---------

void Fnc_Revr(char *str){
  int i,n;
  char c;

  n=strlen(str);
  for(i = 0;i < n / 2;i++){
    c=str[i];
    str[i]=str[n - i - 1];
    str[n - i - 1]=c;
  }
}

//----------  Function Encorder STEP  ---------

void Fnc_Stp(){
  if(Enc_Stp == 10000)                   // Step = 10kHz ?
    Enc_Stp = 10;                        //   Yes,100khz set
  else
    Enc_Stp = Enc_Stp * 10;              // Step up 1 digit

  Fnc_Step_Disp();
  while(digitalRead(SW_STEP) == LOW)
    ;
  delay(50);
}

//----------  Function STEP Display  ----------

void Fnc_Step_Disp(){
  lcd.setCursor(0,1);
  switch(Enc_Stp){
    case 10:
      lcd.print("Step10 ");
      break;
    case 100:
      lcd.print("Step100");
      break;
    case 1000:
      lcd.print("Step1k ");
      break;
    case 10000:
      lcd.print("Step10k");
      break;
    default:
      lcd.print("Step10 ");
      Enc_Stp = 10;
      break;
  }
}


     

19 件のコメント:

G2 さんのコメント...

こんにちは、ARDUINO NANOのために、このプロジェクトのバージョンがありますか???

JA2GQP さんのコメント...

残念ですがありません。

G2 さんのコメント...

ありがとう、Akio。
このプロジェクトに興味がありますか?
プログラムはarduino pro miniにロードする準備ができていますか?
何か追加する必要がありますか?
ありがとうLW4DZC(アルゼンチン)

G2 さんのコメント...

とても良いブログです。
おめでとうございます

JA2GQP さんのコメント...

日本語でのコメントありがとうございました。

G2 さんのコメント...

K4GC OFVかどうか知りたい
うまく動作するか、何らかの欠陥があります。
ありがとう LW4DZC (Argentina)

G2 さんのコメント...

I want to know if the K4GC OFV
works well or has some defect ..
Thank you LW4DZC Argentina

JA2GQP さんのコメント...

K4GCのVFOはボリュームを使ったアナログコントロールで動作不良でした。その為、エンコーダを使った処理にしました。

G2 さんのコメント...

私はこのプロジェクトを作りたいです。
興味がある
うまくいくことを願っています
お返事ありがとうございます

G2 さんのコメント...

SKETCH LOAD ERROR

#include

si5351.h: No such file or directory

G2 さんのコメント...

#include
si5351.h: No such file or directory

G2 さんのコメント...

こんにちは、画面には完全なメニューが表示されますが、常に7030.00です。ステップを変更することはできますが、周波数はエンコーダーで変更されません。
問題は何ですか?
ありがとう

JA2GQP さんのコメント...

G2さん こんにちは
挙動がおかしいとの事でしたので、環境を作って試験しました。
エンコーダの配線に問題なければ、動作します。(動作するはずです。)
si5351の線が外れていても、エンコーダ操作で表示器は変わります。
問題は、エンコーダ配線不良または、半田付け不良と思われます。

G2 さんのコメント...

I detect that the problem due to the next line.
´
'unsigned char result = r.process ();'

The process() function from Rotary.h is returning always empety (DIR_NONE) so it never enter de if statament.


Do you ever have this problem?

I try adding r.begin() in the setup by reading rotary documentation (https://github.com/brianlow/Rotary) but doesnt work.

Thank you.

JA2GQP さんのコメント...

G2
Sometimes I have problems, but I can't say anything because I don't have version control for the library.

G2 さんのコメント...

I am using the latest version of the arduino IDE. It is convenient to use an older version for this project.
which version of arduino do you recommend using ???
Thank you so much

JA2GQP さんのコメント...


Hi G2.
I use the latest Arduino IDE. You don't seem to know where the problem lies. The problem is in Rotary.h. Download the Rotary library here.
https://github.com/buxtronix/arduino

G2 さんのコメント...

Thank you very much for your help!!!!!
The vfo works perfectly now ..
A faulty solder on the chip generated the problem. Now it works very well !!!
Thanks and sorry for bothering.
LW4DZC

JA2GQP さんのコメント...

Hi LW4DZC.
I was relieved to work.
I wish you all the best. 73.