scroll wheel is now done with a stochastic algorithm to make up for the inherent noise in the phototransistor
This commit is contained in:
		
							parent
							
								
									fc9cd621b1
								
							
						
					
					
						commit
						26bcddb623
					
				| 
						 | 
				
			
			@ -17,6 +17,9 @@
 | 
			
		|||
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(ARDUINO) && ARDUINO >= 100
 | 
			
		||||
#include "Arduino.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "Scroller.h"
 | 
			
		||||
 | 
			
		||||
Scroller::Scroller(void) {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,15 +28,29 @@ Scroller::Scroller(void) {
 | 
			
		|||
  hilof = false;
 | 
			
		||||
  lowA = 1023;
 | 
			
		||||
  highA = 0;
 | 
			
		||||
  cLowA = false;
 | 
			
		||||
  cHighA = false;
 | 
			
		||||
  lowIndexA = 0;
 | 
			
		||||
  highIndexA = 0;
 | 
			
		||||
  lowOverflowA = false;
 | 
			
		||||
  highOverflowA = false;
 | 
			
		||||
  lowB = 1023;
 | 
			
		||||
  highB = 0;
 | 
			
		||||
  cLowB = false;
 | 
			
		||||
  cHighB = false;
 | 
			
		||||
  lowIndexB = 0;
 | 
			
		||||
  highIndexB = 0;
 | 
			
		||||
  lowOverflowB = false;
 | 
			
		||||
  highOverflowB = false;
 | 
			
		||||
  scrollThresholdA = 0;
 | 
			
		||||
  scrollThresholdB = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::scroll(int curA, int curB) {
 | 
			
		||||
  calculateThresholdA(curA);
 | 
			
		||||
  calculateThresholdB(curB);
 | 
			
		||||
  if (lowOverflowA == false || highOverflowA == false)
 | 
			
		||||
    calculateThresholdA(curA);
 | 
			
		||||
  if (lowOverflowB == false || highOverflowB == false)
 | 
			
		||||
    calculateThresholdB(curB);
 | 
			
		||||
 | 
			
		||||
  bool LO = false;
 | 
			
		||||
  bool HI = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -109,36 +126,147 @@ int Scroller::scroll(int curA, int curB) {
 | 
			
		|||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::getScrollThresholdA(void) {
 | 
			
		||||
  return scrollThresholdA;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::al(void) {
 | 
			
		||||
  return lowA;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::ah(void) {
 | 
			
		||||
  return highA;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::getScrollThresholdB(void) {
 | 
			
		||||
  return scrollThresholdB;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::calculateThresholdA(int curA) {
 | 
			
		||||
  if (curA < lowA)
 | 
			
		||||
    lowA = curA;
 | 
			
		||||
  else if (curA > highA)
 | 
			
		||||
    highA = curA;
 | 
			
		||||
 | 
			
		||||
  scrollThresholdA = ((highA - lowA) / 3) + lowA;
 | 
			
		||||
  scrollThresholdA = calculateThreshold(curA, lowA, highA,
 | 
			
		||||
    cLowA, cHighA, arLowA, arHighA, lowIndexA, highIndexA,
 | 
			
		||||
    lowOverflowA, highOverflowA);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::calculateThresholdB(int curB) {
 | 
			
		||||
  if (curB < lowB)
 | 
			
		||||
    lowB = curB;
 | 
			
		||||
  else if (curB > highB)
 | 
			
		||||
    highB = curB;
 | 
			
		||||
 | 
			
		||||
  scrollThresholdB = ((highB - lowB) / 3) + lowB;
 | 
			
		||||
  scrollThresholdB = calculateThreshold(curB, lowB, highB,
 | 
			
		||||
    cLowB, cHighB, arLowB, arHighB, lowIndexB, highIndexB,
 | 
			
		||||
    lowOverflowB, highOverflowB);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::calculateThreshold(int cur, int &low, int &high,
 | 
			
		||||
    bool &cLow, bool &cHigh, int arLow[], int arHigh[],
 | 
			
		||||
    int &lowIndex, int &highIndex, bool &lowOverflow,
 | 
			
		||||
    bool &highOverflow) {
 | 
			
		||||
 | 
			
		||||
  if (cur < low)
 | 
			
		||||
    low = cur;
 | 
			
		||||
  if (cur > high)
 | 
			
		||||
    high = cur;
 | 
			
		||||
 | 
			
		||||
  int curThresh = thresholdEquation(low, high);
 | 
			
		||||
  int range = high - low;
 | 
			
		||||
 | 
			
		||||
  // The range is enforced to be over a certain limit because noise
 | 
			
		||||
  // can cause erroneous readings, making these calculations unstable.
 | 
			
		||||
  if (range >= THRESH_RANGE_LIM) {
 | 
			
		||||
    if (cur < curThresh) {
 | 
			
		||||
      if (cHigh == true) {
 | 
			
		||||
        // We were just high, and now we crossed to low.
 | 
			
		||||
        // high reflects a sample of a high reading.
 | 
			
		||||
        arHigh[highIndex] = high;
 | 
			
		||||
        incrementIndex(highIndex, highOverflow);
 | 
			
		||||
        int midpoint = ((high - low) / 2) + low;
 | 
			
		||||
        low = midpoint;
 | 
			
		||||
        high = midpoint;
 | 
			
		||||
        cLow = false;
 | 
			
		||||
        cHigh = false;
 | 
			
		||||
      } else {
 | 
			
		||||
        cLow = true;
 | 
			
		||||
      }
 | 
			
		||||
    } if (cur > curThresh) {
 | 
			
		||||
      if (cLow == true) {
 | 
			
		||||
        // We were just low, and now we crossed to high.
 | 
			
		||||
        // low reflects a sample of a low reading.
 | 
			
		||||
        arLow[lowIndex] = low;
 | 
			
		||||
        incrementIndex(lowIndex, lowOverflow);
 | 
			
		||||
        int midpoint = ((high - low) / 2) + low;
 | 
			
		||||
        low = midpoint;
 | 
			
		||||
        high = midpoint;
 | 
			
		||||
        cLow = false;
 | 
			
		||||
        cHigh = false;
 | 
			
		||||
      } else {
 | 
			
		||||
        cHigh = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int calcHigh = 0;
 | 
			
		||||
  if (highOverflow == true) {
 | 
			
		||||
    for (int i = 0; i < SCROLLER_AR_SIZE; i++) {
 | 
			
		||||
      calcHigh += arHigh[i];
 | 
			
		||||
    }
 | 
			
		||||
    calcHigh = calcHigh / SCROLLER_AR_SIZE;
 | 
			
		||||
  } else if (highIndex != 0) {
 | 
			
		||||
    for (int i = 0; i < highIndex; i++) {
 | 
			
		||||
      calcHigh += arHigh[i];
 | 
			
		||||
    }
 | 
			
		||||
    calcHigh = calcHigh / highIndex;
 | 
			
		||||
  } else {
 | 
			
		||||
    calcHigh = high;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int calcLow = 0;
 | 
			
		||||
  if (lowOverflow == true) {
 | 
			
		||||
    for (int i = 0; i < SCROLLER_AR_SIZE; i++) {
 | 
			
		||||
      calcLow += arLow[i];
 | 
			
		||||
    }
 | 
			
		||||
    calcLow = calcLow / SCROLLER_AR_SIZE;
 | 
			
		||||
  } else if (lowIndex != 0) {
 | 
			
		||||
    for (int i = 0; i < lowIndex; i++) {
 | 
			
		||||
      calcLow += arLow[i];
 | 
			
		||||
    }
 | 
			
		||||
    calcLow = calcLow / lowIndex;
 | 
			
		||||
  } else {
 | 
			
		||||
    calcLow = low;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return thresholdEquation(calcLow, calcHigh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Scroller::thresholdEquation(int lo, int hi) {
 | 
			
		||||
  return ((hi - lo) / 3) + lo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Scroller::incrementIndex(int &index, bool &ovflw) {
 | 
			
		||||
  if (index < SCROLLER_AR_SIZE - 1)
 | 
			
		||||
    index++;
 | 
			
		||||
  else {
 | 
			
		||||
    index = 0;
 | 
			
		||||
    ovflw = true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Scroller::debug(void) {
 | 
			
		||||
  /*
 | 
			
		||||
  Serial.print(F("lowA: "));
 | 
			
		||||
  Serial.print(lowA);
 | 
			
		||||
  Serial.print(F(", highA: "));
 | 
			
		||||
  Serial.print(highA);
 | 
			
		||||
  Serial.print(F(", cLowA: "));
 | 
			
		||||
  Serial.print(cLowA ? "true" : "false");
 | 
			
		||||
  Serial.print(F(", cHighA: "));
 | 
			
		||||
  Serial.print(cHighA ? "true" : "false");
 | 
			
		||||
  Serial.print(F(", lowIndexA: "));
 | 
			
		||||
  Serial.print(lowIndexA);
 | 
			
		||||
  Serial.print(F(", highIndexA: "));
 | 
			
		||||
  Serial.print(highIndexA);
 | 
			
		||||
  Serial.print(F(", lowOverflowA: "));
 | 
			
		||||
  Serial.print(lowOverflowA ? "true" : "false");
 | 
			
		||||
  Serial.print(F(", highOverflowA: "));
 | 
			
		||||
  Serial.println(highOverflowA ? "true" : "false");
 | 
			
		||||
 | 
			
		||||
  Serial.print(F("arLowA: "));
 | 
			
		||||
  for (int i = 0; i < SCROLLER_AR_SIZE; i++) {
 | 
			
		||||
    Serial.print(arLowA[i]);
 | 
			
		||||
    Serial.print(F(","));
 | 
			
		||||
  }
 | 
			
		||||
  Serial.println(".");
 | 
			
		||||
 | 
			
		||||
  Serial.print(F("arHighA: "));
 | 
			
		||||
  for (int i = 0; i < SCROLLER_AR_SIZE; i++) {
 | 
			
		||||
    Serial.print(arHighA[i]);
 | 
			
		||||
    Serial.print(F(","));
 | 
			
		||||
  }
 | 
			
		||||
  Serial.println(".");
 | 
			
		||||
  */
 | 
			
		||||
  
 | 
			
		||||
  Serial.print(F(", thB: "));
 | 
			
		||||
  Serial.print(scrollThresholdB);
 | 
			
		||||
  Serial.print(F(", thA: "));
 | 
			
		||||
  Serial.print(scrollThresholdA);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,30 +17,51 @@
 | 
			
		|||
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef SCROLLER_AR_SIZE
 | 
			
		||||
#define SCROLLER_AR_SIZE 40
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef SCROLLER_h
 | 
			
		||||
#define SCROLLER_h
 | 
			
		||||
 | 
			
		||||
class Scroller {
 | 
			
		||||
  private:
 | 
			
		||||
    const int THRESH_RANGE_LIM = 10;
 | 
			
		||||
    enum State { HIHI, HILO, LOLO, LOHI };
 | 
			
		||||
    State state;
 | 
			
		||||
    bool lohif;
 | 
			
		||||
    bool hilof;
 | 
			
		||||
    int lowA;
 | 
			
		||||
    int highA;
 | 
			
		||||
    bool cLowA;
 | 
			
		||||
    bool cHighA;
 | 
			
		||||
    int lowIndexA;
 | 
			
		||||
    int highIndexA;
 | 
			
		||||
    bool lowOverflowA;
 | 
			
		||||
    bool highOverflowA;
 | 
			
		||||
    int lowB;
 | 
			
		||||
    int highB;
 | 
			
		||||
    bool cLowB;
 | 
			
		||||
    bool cHighB;
 | 
			
		||||
    int lowIndexB;
 | 
			
		||||
    int highIndexB;
 | 
			
		||||
    bool lowOverflowB;
 | 
			
		||||
    bool highOverflowB;
 | 
			
		||||
    int scrollThresholdA;
 | 
			
		||||
    int scrollThresholdB;
 | 
			
		||||
    int arLowA[SCROLLER_AR_SIZE];
 | 
			
		||||
    int arHighA[SCROLLER_AR_SIZE];
 | 
			
		||||
    int arLowB[SCROLLER_AR_SIZE];
 | 
			
		||||
    int arHighB[SCROLLER_AR_SIZE];
 | 
			
		||||
    int calculateThresholdA(int);
 | 
			
		||||
    int calculateThresholdB(int);
 | 
			
		||||
    int calculateThreshold(int, int&, int&, bool&, bool&, int*, int*, int&, int&, bool&, bool&);
 | 
			
		||||
    int thresholdEquation(int, int);
 | 
			
		||||
    void incrementIndex(int&, bool&);
 | 
			
		||||
  public:
 | 
			
		||||
    Scroller(void);
 | 
			
		||||
    int scroll(int, int);
 | 
			
		||||
    int getScrollThresholdA(void);
 | 
			
		||||
    int getScrollThresholdB(void);
 | 
			
		||||
    int al(void);
 | 
			
		||||
    int ah(void);
 | 
			
		||||
    void debug(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -400,8 +400,7 @@ signed char moveWheel() {
 | 
			
		|||
  int d2 = analogRead(OPT_ENC_PIN2);
 | 
			
		||||
 | 
			
		||||
  if (debugMode) {
 | 
			
		||||
    Serial.print(F("th: "));
 | 
			
		||||
    Serial.print(scroller.getScrollThreshold());
 | 
			
		||||
    scroller.debug();
 | 
			
		||||
    Serial.print(F(", d1: "));
 | 
			
		||||
    Serial.print(d1);
 | 
			
		||||
    Serial.print(F(", d2: "));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue