Hy there Drake,
For what it's worth and maybe some reading material for the holidays.
I wrote some code a while back to do something similar.
/*
Update: ver.03 08/02/2019
Clean up unused variables
Clean up layout
*/
/*
Purpose: Double 4x Bi-directional encoding
to represent the X-Y axis of a 2d object
and log it in .csv format.
Board: Arduino Mega 2560
Optical encoder open collector
Author: Gij Kieken
Date: 22/01/2019
Info: I am using two diferent methods to determine
the X and Y position
One with a switch case construction and one
with an array.
*/
// Used functions
/* myDebounceShortLongPress
Purpose: Debounce an array of push buttons and determine if they
where pressed a short or long time.(micro seconds)
In setup use pinMode(pin, INPUT_PULLUP) so no external
components are necessary.
Buttons connected 1-side to gnd the other to Arduino pin.
Author: Gij Kieken
*/
const byte maxButton = 3; //Number of buttons
const byte pinPushButton[maxButton] = {4, 5, 6}; //Arduino IN pins
const byte maxOutput = 4; //Number of outputs
const byte LED[maxOutput] = {9, 10, 11, 12}; //Arduino OUT pins
volatile long countX = 0;
volatile long countY = 0;
boolean A, B;
boolean C, D;
boolean modeStatus = false; // Keep track of Hole or Line mode
boolean printHeaderHole = true; // Print header once
boolean printHeaderLine = false; // Print header once
boolean printHeaderStop = false; // Print header once
//**********************
const unsigned long interval = 500000;
unsigned long previousStartMicros;
unsigned long previousStopMicros;
boolean enabledStop = false;
boolean enabledStart = false;
//***********************
byte stateX, statepX;
byte stateY, statepY;
//Quadrature Encoder Matrix
const byte QEM[16] = {0, -1, 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, -1, 0, 1, 0};
byte index = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(2, INPUT);//Channel A
pinMode(3, INPUT);//Channel B
pinMode(21, INPUT);//Channel C
pinMode(20, INPUT); //Channel D
//Initialize push button pins as inputs with pull-ups
// button[0]=startButton, button[1]=stopButton, button[2]=modeButton
for (byte i = 0; i < maxButton; i++) {
pinMode(pinPushButton[i], INPUT_PULLUP);
}
//Initialize LED pins as outputs
// LED[0]=HoleLed, LED[1]= LineLed, LED[2]=StartLed, LED[3]=StopLed
for (byte j = 0; j < maxOutput; j++) {
pinMode(LED[j], OUTPUT);
}
digitalWrite(LED[0], !modeStatus); //We start in hole mode
digitalWrite(LED[1], modeStatus); //LineLED=OFF
digitalWrite(LED[2], LOW); //StartLed=OFF
digitalWrite(LED[3], LOW); //StopLed=OFF
attachInterrupt(digitalPinToInterrupt(2), Achange, CHANGE); //Int 0
attachInterrupt(digitalPinToInterrupt(3), Bchange, CHANGE); //Int 1
attachInterrupt(digitalPinToInterrupt(21), Cchange, CHANGE); //Int 2
attachInterrupt(digitalPinToInterrupt(20), Dchange, CHANGE); //Int 3
//read the initial value of A & B
A = digitalRead(2);
B = digitalRead(3);
//read the initial value of C & D
C = digitalRead(21);
D = digitalRead(20);
//set initial stateX value
if ((A == HIGH) && (B == HIGH)) statepX = 1;
if ((A == HIGH) && (B == LOW)) statepX = 2;
if ((A == LOW) && (B == LOW)) statepX = 3;
if ((A == LOW) && (B == HIGH)) statepX = 4;
//set initial stateY value
if ((C == HIGH) && (D == HIGH)) statepY = 1;
if ((C == HIGH) && (D == LOW)) statepY = 2;
if ((C == LOW) && (D == LOW)) statepY = 3;
if ((C == LOW) && (D == HIGH)) statepY = 4;
// Start communication with Excel
Serial.println("CLEARSHEET");
Serial.println("LABEL,X-Pos,Y-Pos");
Serial.println("CELL,SET,C01, Gij Kieken X-Y pos ");
Serial.println("CELL,SET,C02, Long press Start to start log.");
Serial.println("CELL,SET,C03, Short press Start to tween.");
Serial.println("CELL,SET,C04, Short press mode to toggle.");
Serial.println("CELL,SET,C05, Short press Stop to stop log.");
Serial.println("DATA,HOLE-X,HOLE-Y");
}
void loop() {
// put your main code here, to run repeatedly:
static unsigned long previousTime = 0;
const byte timeInterval = 2000; //pick a short time interval
byte button[maxButton] = {}; //array to store the latest readings
// button[0]=startButton, button[1]=stopButton, button[2]=modeButton
// LED[0]=HoleLed, LED[1]= LineLed, LED[2]=StartLed, LED[3]=StopLed
// - check all buttons
if ((micros() - previousTime) > timeInterval) {
previousTime = micros();
for (byte i = 0; i < maxButton; i++) {
button[i] = checkButtons(i);
}
if (button[0] == 1) { // Code, when Start button is short-pushed
//***Continue to Log***
if (enabledStart) {
digitalWrite(LED[2], HIGH);
Serial.print("DATA,");
Serial.print(countX);
Serial.print(",");
Serial.println(countY);
Serial.println("BEEP");
previousStartMicros = micros();
}
}
if (button[0] == 2) { // Code, when Start button is long-pushed
//***Start to Log***
if (!enabledStart) {
digitalWrite(LED[2], HIGH);
enabledStart = true;
// Reset countX and countY
countX = 0;
countY = 0;
Serial.print("DATA,");
Serial.print(countX);
Serial.print(",");
Serial.println(countY);
Serial.println("BEEP");
previousStartMicros = micros();
}
}
if (button[1] == 1) { // Code, when Stop button is short-pushed
//***Stop to Log***
digitalWrite( LED[3], HIGH); // turn on led
if (!printHeaderStop) {
Serial.println("DATA,STOPPED-X,STOPPED-Y"); // Print header
// Reset the flags
modeStatus = LOW; // Reset modeStatus to hole mode
printHeaderLine = false;
printHeaderStop = true; // Make sure header is printed only once
enabledStart = false; // Reset the start flag
enabledStop = true; // Print offset X=0,Y=0 once
digitalWrite(LED[0], !modeStatus); // Change hole led state
digitalWrite(LED[1], modeStatus); // Change line led state
Serial.println("DATA,HOLE-X,HOLE-Y");
Serial.println("BEEP");
Serial.println("SAVEWORKBOOKAS,MyNewX-Y_pos");
printHeaderHole = true;
previousStopMicros = micros();
}
}
if (button[2] == 1) { // Code, when Mode button is short-pushed
//***Select the mode***
// modeStatus=0 ---> hole-modus, modeStatus=1 ---> line-modus
modeStatus = !modeStatus; // Toggle the LED value
digitalWrite(LED[0], !modeStatus); // Change hole led state
digitalWrite(LED[1], modeStatus); // Change line led state
//***Determine mode Hole or Line and printout appropriate header***
if (!modeStatus && !printHeaderHole && printHeaderLine) {
Serial.println("DATA,HOLE-X,HOLE-Y");
Serial.println("BEEP");
printHeaderHole = true; // Make sure header is printed only once
printHeaderLine = false;
}
else if (modeStatus && printHeaderHole && !printHeaderLine) {
Serial.println("DATA,LINE-X,LINE-Y");
Serial.println("BEEP");
printHeaderLine = true;
printHeaderHole = false;
}
}
}
// Switch off start led
if ( micros() - previousStartMicros >= interval) {
digitalWrite( LED[2], LOW); // turn off led
}
// Switch off stop led
if ( enabledStop) { // software timer is active
if ( micros() - previousStopMicros >= interval) {
digitalWrite( LED[3], LOW); // turn off led
enabledStop = false; // stop software timer
printHeaderStop = false; // Reset flag
}
}
} // End void loop()
//************************************************************************
/* Function: Checks one button for short or long press (micro seconds)
Accepts a byte for the button number
Returns a byte 0-none 1-short 2-long
Info: Action is executed when release button
*/
byte checkButtons(byte buttonNo) {
const unsigned long timeDebounce = 100000;//time to debounce
const unsigned long timeLong = 1000000; //minimum time for Long press
const unsigned long timeBreak = 200000; //time interval after button release,
//before ready for next press
static byte state[maxButton] = {}; //this initializes all elements to zero
static unsigned long previousTime[maxButton] = {};//this initializes all elements to zero
byte r = 0; // 0:not 1:short 2:long
if (state[buttonNo] == 0) { //no button has been pressed - check if
if (digitalRead(pinPushButton[buttonNo]) == LOW) {
previousTime[buttonNo] = micros();
state[buttonNo] = 1;
}
} else if (state[buttonNo] == 1) { //button was pressed - check for how long
if ( (micros() - previousTime[buttonNo]) > timeDebounce) {
if ( (micros() - previousTime[buttonNo]) < timeLong) {
if ( digitalRead(pinPushButton[buttonNo]) == HIGH) { //released -> short press
previousTime[buttonNo] = micros();
state[buttonNo] = 3;
r = 1;
}
} else { //it was a long press
state[buttonNo] = 2;
r = 2;
}
}
} else if (state[buttonNo] == 2) { //wait for long button press to end
if (digitalRead(pinPushButton[buttonNo]) == HIGH) {
previousTime[buttonNo] = micros();
state[buttonNo] = 3;
}
} else if (state[buttonNo] == 3) { //wait a little while after previous button press
if ( (micros() - previousTime[buttonNo]) > timeBreak) {
state[buttonNo] = 0;
}
}
return r;
}
void Achange() {
A = digitalRead(2);
B = digitalRead(3);
//determine state value
if ((A == HIGH) && (B == HIGH)) stateX = 1;
if ((A == HIGH) && (B == LOW)) stateX = 2;
if ((A == LOW) && (B == LOW)) stateX = 3;
if ((A == LOW) && (B == HIGH)) stateX = 4;
switch (stateX) {
case 1:
{
if (statepX == 2) countX--;
if (statepX == 4) countX++;
break;
}
case 2:
{
if (statepX == 1) countX++;
if (statepX == 3) countX--;
break;
}
case 3:
{
if (statepX == 2) countX++;
if (statepX == 4) countX--;
break;
}
default:
{
if (statepX == 1) countX--;
if (statepX == 3) countX++;
}
}
statepX = stateX;
}
void Bchange() {
A = digitalRead(2);
B = digitalRead(3);
//determine state value
if ((A == HIGH) && (B == HIGH)) stateX = 1;
if ((A == HIGH) && (B == LOW)) stateX = 2;
if ((A == LOW) && (B == LOW)) stateX = 3;
if ((A == LOW) && (B == HIGH)) stateX = 4;
switch (stateX) {
case 1:
{
if (statepX == 2) countX--;
if (statepX == 4) countX++;
break;
}
case 2:
{
if (statepX == 1) countX++;
if (statepX == 3) countX--;
break;
}
case 3:
{
if (statepX == 2) countX++;
if (statepX == 4) countX--;
break;
}
default:
{
if (statepX == 1) countX--;
if (statepX == 3) countX++;
}
}
statepX = stateX;
}
//*********************************************
void Cchange() {
C = digitalRead(21);
D = digitalRead(20);
//Determine state value
if ((C == HIGH) && (D == HIGH)) stateY = 0;
if ((C == HIGH) && (D == LOW)) stateY = 1;
if ((C == LOW) && (D == LOW)) stateY = 2;
if ((C == LOW) && (D == HIGH)) stateY = 3;
index = 4 * stateY + statepY;
countY = countY + QEM[index];
statepY = stateY;
}
void Dchange() {
C = digitalRead(21);
D = digitalRead(20);
//Determine state value
if ((C == HIGH) && (D == HIGH)) stateY = 0;
if ((C == HIGH) && (D == LOW)) stateY = 1;
if ((C == LOW) && (D == LOW)) stateY = 2;
if ((C == LOW) && (D == HIGH)) stateY = 3;
index = 4 * stateY + statepY;
countY = countY + QEM[index];
statepY = stateY;
}
Have fun,,,