2017年1月19日 星期四

旋轉編碼器消除彈跳











/*
  RotaryEncoderInterrupt sketch
  2017-01-19 test OK
 */

const int encoderPinA = 2;
const int encoderPinB = 3;
int Pos, oldPos;
volatile int encoderPos = 0; // variables changed within interrupts are volatile

void setup(){
  pinMode(6, OUTPUT);  digitalWrite(6, LOW); //encoder Gnd
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  Serial.begin(115200);
  attachInterrupt(1, doEncoder, CHANGE); // encoder pin on interrupt 0 (pin 3)
 // attachInterrupt(0, doEncoder, FALLING); // encoder pin on interrupt 0 (pin 2)
}

void loop(){
  uint8_t oldSREG = SREG;
  cli();  Pos = encoderPos;  SREG = oldSREG;  if(Pos != oldPos)
  {
    Serial.println(Pos,DEC);    oldPos = Pos;
  }
  delay(10);
}


void doEncoder(){
  if (digitalRead(encoderPinA) == digitalRead(encoderPinB))
    encoderPos++;    // count up if both encoder pins are the same
  else
    encoderPos--;    //count down if pins are different
}



接著發現一個狀況~~
若需設定的值範圍很大時不就要轉很久 ...

利用轉動速度快慢(偵測脈波寬度)的方式來決定增量的值


/*
  RotaryEncoderInterrupt sketch
  2017-01-20 test OK
 */

const int encoderPinA = 2;
const int encoderPinB = 3;
int Pos, oldPos;
unsigned long duration;
volatile int encoderPos = 0; // variables changed within interrupts are volatile

void setup(){
  pinMode(6, OUTPUT);  digitalWrite(6, LOW); //encoder Gnd
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  Serial.begin(115200);
  attachInterrupt(1, doEncoder, CHANGE); // encoder pin on interrupt 0 (pin 3)
 // attachInterrupt(0, doEncoder, FALLING); // encoder pin on interrupt 0 (pin 2)
}

void loop(){
  uint8_t oldSREG = SREG;
  cli();  Pos = encoderPos;  SREG = oldSREG;  if(Pos != oldPos){
    Serial.print(Pos,DEC); 
    Serial.print(",   Pulse Width /nS :");
    Serial.println(duration,DEC); 
    oldPos = Pos;
  }
  delay(10);
  duration = pulseIn(encoderPinA, HIGH,100000);
}


void doEncoder(){
  if (digitalRead(encoderPinA) == digitalRead(encoderPinB)){
    if(duration == 0 || duration >= 35001)encoderPos++;
    if(duration >= 1 && duration <= 35000)encoderPos += 20;
    if(duration >= 1 && duration <= 10000)encoderPos += 80;
  }   
  else{
    if(duration == 0 || duration >= 35001)encoderPos--;
    if(duration >= 1 && duration <= 35000)encoderPos -= 20;
    if(duration >= 1 && duration <= 10000)encoderPos -= 80;
     }
}


 轉一格有 1個訊號
//2018-06-26 test OK 



volatile long posCount = 0;
unsigned long t = 0;

void setup() {
  Serial.begin(115200);
  // 當狀態下降時,代表旋轉編碼器被轉動了
  attachInterrupt(1, rotaryEncoderChanged, FALLING);  //INT 1 -> pin 3
  pinMode(3, INPUT_PULLUP); // 輸入模式並啟用內建上拉電阻
  pinMode(4, INPUT_PULLUP); 
  pinMode(5, INPUT_PULLUP); 
  Serial.println("count reset to 0");
}

long position  = -999;
word position1,newPos1;


void loop() {
//delay(500);  
if (posCount != position) {
 position = posCount;
 Serial.println(position);
}

  if(digitalRead(5) == LOW){ // 按下開關,歸零
     posCount = 0;  
     delay(300);
  }
}


void rotaryEncoderChanged(){ // when CLK_PIN is FALLING
//  unsigned long temp = millis();  // 去彈跳
//  if(temp - t < 20)               // 去彈跳
//    return;                       // 去彈跳
//  t = temp;                       // 去彈跳
  
  // DT_PIN的狀態代表正轉或逆轉
  posCount += digitalRead(4) == HIGH ? 1 : -1;
 // Serial.println(count);
}



可以不使用中斷的 Library  ->   https://github.com/PaulStoffregen/Encoder
轉一格有 4個訊號