scroll wheel is now done with a stochastic algorithm to make up for the inherent noise in the phototransistor

This commit is contained in:
PloopyCo 2019-11-25 12:33:00 -05:00
parent fc9cd621b1
commit 26bcddb623
3 changed files with 186 additions and 38 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -393,15 +393,14 @@ signed char moveWheel() {
if (middleButtonPin == LOW) {
return 0;
}
lastScroll = micros();
int d1 = analogRead(OPT_ENC_PIN1);
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: "));