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
 | 
					 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(ARDUINO) && ARDUINO >= 100
 | 
				
			||||||
 | 
					#include "Arduino.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#include "Scroller.h"
 | 
					#include "Scroller.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Scroller::Scroller(void) {
 | 
					Scroller::Scroller(void) {
 | 
				
			||||||
| 
						 | 
					@ -25,14 +28,28 @@ Scroller::Scroller(void) {
 | 
				
			||||||
  hilof = false;
 | 
					  hilof = false;
 | 
				
			||||||
  lowA = 1023;
 | 
					  lowA = 1023;
 | 
				
			||||||
  highA = 0;
 | 
					  highA = 0;
 | 
				
			||||||
 | 
					  cLowA = false;
 | 
				
			||||||
 | 
					  cHighA = false;
 | 
				
			||||||
 | 
					  lowIndexA = 0;
 | 
				
			||||||
 | 
					  highIndexA = 0;
 | 
				
			||||||
 | 
					  lowOverflowA = false;
 | 
				
			||||||
 | 
					  highOverflowA = false;
 | 
				
			||||||
  lowB = 1023;
 | 
					  lowB = 1023;
 | 
				
			||||||
  highB = 0;
 | 
					  highB = 0;
 | 
				
			||||||
 | 
					  cLowB = false;
 | 
				
			||||||
 | 
					  cHighB = false;
 | 
				
			||||||
 | 
					  lowIndexB = 0;
 | 
				
			||||||
 | 
					  highIndexB = 0;
 | 
				
			||||||
 | 
					  lowOverflowB = false;
 | 
				
			||||||
 | 
					  highOverflowB = false;
 | 
				
			||||||
  scrollThresholdA = 0;
 | 
					  scrollThresholdA = 0;
 | 
				
			||||||
  scrollThresholdB = 0;
 | 
					  scrollThresholdB = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int Scroller::scroll(int curA, int curB) {
 | 
					int Scroller::scroll(int curA, int curB) {
 | 
				
			||||||
 | 
					  if (lowOverflowA == false || highOverflowA == false)
 | 
				
			||||||
    calculateThresholdA(curA);
 | 
					    calculateThresholdA(curA);
 | 
				
			||||||
 | 
					  if (lowOverflowB == false || highOverflowB == false)
 | 
				
			||||||
    calculateThresholdB(curB);
 | 
					    calculateThresholdB(curB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool LO = false;
 | 
					  bool LO = false;
 | 
				
			||||||
| 
						 | 
					@ -109,36 +126,147 @@ int Scroller::scroll(int curA, int curB) {
 | 
				
			||||||
  return ret;
 | 
					  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) {
 | 
					int Scroller::calculateThresholdA(int curA) {
 | 
				
			||||||
  if (curA < lowA)
 | 
					  scrollThresholdA = calculateThreshold(curA, lowA, highA,
 | 
				
			||||||
    lowA = curA;
 | 
					    cLowA, cHighA, arLowA, arHighA, lowIndexA, highIndexA,
 | 
				
			||||||
  else if (curA > highA)
 | 
					    lowOverflowA, highOverflowA);
 | 
				
			||||||
    highA = curA;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  scrollThresholdA = ((highA - lowA) / 3) + lowA;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int Scroller::calculateThresholdB(int curB) {
 | 
					int Scroller::calculateThresholdB(int curB) {
 | 
				
			||||||
  if (curB < lowB)
 | 
					  scrollThresholdB = calculateThreshold(curB, lowB, highB,
 | 
				
			||||||
    lowB = curB;
 | 
					    cLowB, cHighB, arLowB, arHighB, lowIndexB, highIndexB,
 | 
				
			||||||
  else if (curB > highB)
 | 
					    lowOverflowB, highOverflowB);
 | 
				
			||||||
    highB = curB;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  scrollThresholdB = ((highB - lowB) / 3) + lowB;
 | 
					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
 | 
					 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SCROLLER_AR_SIZE
 | 
				
			||||||
 | 
					#define SCROLLER_AR_SIZE 40
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef SCROLLER_h
 | 
					#ifndef SCROLLER_h
 | 
				
			||||||
#define SCROLLER_h
 | 
					#define SCROLLER_h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Scroller {
 | 
					class Scroller {
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
 | 
					    const int THRESH_RANGE_LIM = 10;
 | 
				
			||||||
    enum State { HIHI, HILO, LOLO, LOHI };
 | 
					    enum State { HIHI, HILO, LOLO, LOHI };
 | 
				
			||||||
    State state;
 | 
					    State state;
 | 
				
			||||||
    bool lohif;
 | 
					    bool lohif;
 | 
				
			||||||
    bool hilof;
 | 
					    bool hilof;
 | 
				
			||||||
    int lowA;
 | 
					    int lowA;
 | 
				
			||||||
    int highA;
 | 
					    int highA;
 | 
				
			||||||
 | 
					    bool cLowA;
 | 
				
			||||||
 | 
					    bool cHighA;
 | 
				
			||||||
 | 
					    int lowIndexA;
 | 
				
			||||||
 | 
					    int highIndexA;
 | 
				
			||||||
 | 
					    bool lowOverflowA;
 | 
				
			||||||
 | 
					    bool highOverflowA;
 | 
				
			||||||
    int lowB;
 | 
					    int lowB;
 | 
				
			||||||
    int highB;
 | 
					    int highB;
 | 
				
			||||||
 | 
					    bool cLowB;
 | 
				
			||||||
 | 
					    bool cHighB;
 | 
				
			||||||
 | 
					    int lowIndexB;
 | 
				
			||||||
 | 
					    int highIndexB;
 | 
				
			||||||
 | 
					    bool lowOverflowB;
 | 
				
			||||||
 | 
					    bool highOverflowB;
 | 
				
			||||||
    int scrollThresholdA;
 | 
					    int scrollThresholdA;
 | 
				
			||||||
    int scrollThresholdB;
 | 
					    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 calculateThresholdA(int);
 | 
				
			||||||
    int calculateThresholdB(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:
 | 
					  public:
 | 
				
			||||||
    Scroller(void);
 | 
					    Scroller(void);
 | 
				
			||||||
    int scroll(int, int);
 | 
					    int scroll(int, int);
 | 
				
			||||||
    int getScrollThresholdA(void);
 | 
					    void debug(void);
 | 
				
			||||||
    int getScrollThresholdB(void);
 | 
					 | 
				
			||||||
    int al(void);
 | 
					 | 
				
			||||||
    int ah(void);
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -400,8 +400,7 @@ signed char moveWheel() {
 | 
				
			||||||
  int d2 = analogRead(OPT_ENC_PIN2);
 | 
					  int d2 = analogRead(OPT_ENC_PIN2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (debugMode) {
 | 
					  if (debugMode) {
 | 
				
			||||||
    Serial.print(F("th: "));
 | 
					    scroller.debug();
 | 
				
			||||||
    Serial.print(scroller.getScrollThreshold());
 | 
					 | 
				
			||||||
    Serial.print(F(", d1: "));
 | 
					    Serial.print(F(", d1: "));
 | 
				
			||||||
    Serial.print(d1);
 | 
					    Serial.print(d1);
 | 
				
			||||||
    Serial.print(F(", d2: "));
 | 
					    Serial.print(F(", d2: "));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue