2012年5月4日金曜日

Encoderを使用してDDS_VFOの周波数を変化させる。

[Encoder]

秋月のロータリーエンコーダを使用する。BASCOMでエンコーダを操作するプログラム例はすぐに見つかるがArduinoではなかなか見つからなかった。
dialStep10PinとdialStep1000Pinを同時にOnしてエンコーダを回せば周波数は20kHzごとに変化します。この2つのピンは前日の回路図にあるように1N4148を通じてArduinoに接続する。
但し、まだDDSを接続させてVFOの機能はまだである。KEYの代用しているタクトスイッチを押すと画面表示が変わる。


Sketch


//DDS_TestProgram by JA1NHL  21Apr 2012
//EncodeDisplayKeying
// include the library code:
#include <LiquidCrystal.h>
//LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
#include <Bounce.h>
// usually the rotary encoders three pins have the ground pin in the middle
  int encoderPinA = 2;
  int encoderPinB = 3;
  int dialStep10Pin=8;    
  int dialStep1000Pin=9;
  int ledPin=13;          //monitor
  int keyingPin=19;
  long  Fdata=7000000;
  int  FdataZoubun=100;
  char TxRxState='R';
  volatile long encoderPos = 0;          // a counter for the dial
  volatile long lastReportedPos = 0;      // change management
  static boolean rotating=false;          // debounce management
  boolean A_set = false;                 // interrupt service routine vars          
  boolean B_set = false;
  Bounce bouncer=Bounce(keyingPin,5);
void setup() {
  Serial.begin(9600);               // output for Debug
  lcd.begin(16, 2);                  // set up the LCD's number of columns and rows:
  // Input Output
  pinMode(encoderPinA, INPUT);    
  pinMode(encoderPinB, INPUT);    
  pinMode(dialStep10Pin, INPUT);      
  pinMode(dialStep1000Pin, INPUT);  
  pinMode(keyingPin, INPUT);      
  pinMode(ledPin,OUTPUT);        
  // turn on pullup resistors   内蔵プルアップ
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);
  digitalWrite(dialStep10Pin, HIGH);
  digitalWrite(dialStep1000Pin, HIGH);
  digitalWrite(keyingPin, HIGH);
 //setup the LCD's number of columns and rows;
  lcd.begin(16,2);                      
  lcd.clear();
  attachInterrupt(0, doEncoderA, CHANGE);    // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(1, doEncoderB, CHANGE);    // encoder pin on interrupt 1 (pin 3)
 }
// main loop, work is done by interrupt service routines, this one only prints stuff
void loop() {
  if (digitalRead (keyingPin) ==LOW){
        digitalWrite(ledPin,HIGH);
        TxRxState='T';
   }  else{
         digitalWrite(ledPin,LOW);
         TxRxState='R';
   } displayKeying();
bouncer.update();
int keyingState=bouncer.read();
if(keyingState==LOW){
  digitalWrite(ledPin,HIGH);
  TxRxState='T';
  displayKeying();
    }
    else{
      digitalWrite(ledPin,LOW);
      TxRxState='R';
      displayKeying();
    }
  if (digitalRead (dialStep10Pin) ==LOW){
      if (digitalRead (dialStep10Pin) ==LOW && digitalRead (dialStep1000Pin)==LOW) {
         FdataZoubun=20000; //20kHz
        } else {
         FdataZoubun=10;        
   }
   } else  if (digitalRead (dialStep1000Pin) ==LOW) {
         FdataZoubun=1000;    
   } else {
         FdataZoubun=100;        
   }
   rotating = true;  // reset the debouncer
      if (encoderPos >lastReportedPos ) {   //
       Serial.println(Fdata+FdataZoubun, DEC);
         Serial.println( encoderPos, DEC);
      Fdata= Fdata+FdataZoubun;
           displayEncoder();
             lastReportedPos = encoderPos;
    }
    if (encoderPos < lastReportedPos) {   //
       Serial.println(Fdata-FdataZoubun, DEC);
         Serial.println( encoderPos, DEC);
      Fdata= Fdata-FdataZoubun;
           displayEncoder();
             lastReportedPos = encoderPos;
    }
}

//Subroutine // Interrupt on A changing state
void doEncoderA(){
        // debounce
    if ( rotating ) delay (1);  // wait a little until the bouncing is done
        // Test transition, did things really change?
    if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
      A_set = !A_set;       //! not hitei
      // adjust counter - if A leads B
         if ( A_set && !B_set )
            encoderPos -= 1;
            rotating = false;  // no more debouncing until loop() hits again
    }
}
//Subroutine // Interrupt on B changing state, same as A above
void doEncoderB(){
        //debounce
    if ( rotating ) delay (1);
       //Test transition, did things really change?
    if( digitalRead(encoderPinB) != B_set ) {
      B_set = !B_set;
      //  adjust counter + 1 if B leads A
    if( B_set && !A_set )
        encoderPos += 1;
        rotating = false;
    }
}
//Subroutine display
void displayEncoder(){
     lcd.home();
     String s =String(Fdata) ;
    // String s =String(Fdata+FdataZoubun*encoderPos) ;
     lcd.print("FREQ: ");
     lcd.print(s.charAt(0));
     lcd.print(s.substring(1, 4));
     lcd.print(".");
     lcd.print(s.substring(4,6));
     lcd.print("kHz");
     lcd.setCursor(1,1);
     lcd.print("* RIT:");
     lcd.setCursor(13,1);
     lcd.print("kHz");
}
//Subroutine
void displayKeying(){
       lcd.setCursor(0,1);
       lcd.print(TxRxState);
}
/*
http://www.arduino.cc/playground/Main/RotaryEncoders#Example1
*/
/*
Another Interrupt Library THAT REALLY WORKS (the Encoder
interrupts the processor and
debounces like there is no tomorrow).
by rafbuff
*/

/* interrupt routine for Rotary Encoders
   tested with Noble RE0124PVB 17.7FINB-24 http://www.nobleusa.com/pdf/xre.pdf - available at pollin.de
   and a few others, seems pretty universal
   The average rotary encoder has three pins, seen from front: A C B
   Clockwise rotation A(on)->B(on)->A(off)->B(off)
   CounterCW rotation B(on)->A(on)->B(off)->A(off)
   and may be a push switch with another two pins, pulled low at pin 8 in this case
   raf@synapps.de 20120107
*/

0 件のコメント:

コメントを投稿