/********** 36 Buttons and 3 Rotary Encoders button box by BaldEagle gaming **********/
/*
*This code is for creating a button box with 36 buttons with 3 rotaries and 0 axis
*This code is for Arduino pro micro
*The table below is showing how the buttons are connected to the board (pin)
*A3, A2, A1, A0, 15 and 14 Are the Row Pins for the Keypad 16 and 10-6 are the Column Pins
*the buttons are connected to each others according to this table
* : A3 A2 A1 A1 15 14
* ....................................................
* 16 : 0 1 2 3 4 5 I
* 10 : 6 7 8 9 10 11
* 9 : 12 13 14 15 16 17
* 8 : 18 19 20 21 22 23
* 7 : 24 25 26 27 28 29
* 6 : 30 31 32 33 34 35
* Pin 0, 1, 2, 3, 4, and 5 plus the GND are used for rotaries
*/
//Including libraries and define variables and give a constant value name
#include <Keypad.h> //#include is used to include libraries from outside the code.
#define enablePullUps //#define is used to give a name to a constant value.
//or to define a new variable
const byte numOfRotaries = 1; //creating variables to define number of rotary encoders
//Creating an array with pins that are used
// for more info: 21 = A3, 20 = A2, 19 = A1, 18 = A0 ....
byte colPins[] = {2,A6};
byte rowPins[] = {5,A0};
//define size of array
const int numOfColumns = sizeof(colPins)/sizeof(colPins[0]);
const int numOfRows = sizeof(rowPins)/sizeof(rowPins[0]);
// Creating a 2D array that contains the buttons and also symboling them
byte buttons[numOfRows][numOfColumns] = {
{11,12},
{13,14},
};
//Inislize new keypad class
Keypad ButtonBox = Keypad( makeKeymap(buttons),
rowPins, colPins, numOfRows, numOfColumns);
//creating structure (A structure can contain variables, methods, static constructor, ...)
struct rotariesStruct {
byte pin1; //define pins and create 3 variabes
byte pin2;
int cClockWise;
int clockWise;
volatile unsigned char state;
};
rotariesStruct rotariesEncoders[numOfRotaries] {
//this will create 3 rotaries
{8,9,36,37,0}, //pin 0 and 1 are connected to button 36, 37 (rotary)
};
//rotary table
#define DIR_CCW 0x10 //DIR = Directory
#define DIR_CW 0x20 //ccw = counter clockwise CW = clockwise
#define R_START 0x0 //R_start = rotary start
#ifdef HALF_STEP
//use half step
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5
const unsigned char rotaryTable[6][4] = { //[6][4] mean 6 rows and 4 columns
// R_START (00)
{R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START},
// R_CCW_BEGIN
{R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START},
// R_CW_BEGIN
{R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START},
// R_START_M (11)
{R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START},
// R_CW_BEGIN_M
{R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW},
// R_CCW_BEGIN_M
{R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW},
};
#else
//use full step
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6
const unsigned char rotaryTable[7][4] = { //7*4
// R_START
{R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START},
// R_CW_FINAL
{R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW},
// R_CW_BEGIN
{R_CW_NEXT, R_CW_BEGIN, R_START, R_START},
// R_CW_NEXT
{R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START},
// R_CCW_BEGIN
{R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START},
// R_CCW_FINAL
{R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW},
// R_CCW_NEXT
{R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif
void setup() { //setup() is a method called when the program start, and create the variabes and
//pin mode......
pinMode(0,OUTPUT);
initializeRotaryEncoders();
}
void loop() { //loop() is a method that run for ever
CheckingButtons(); //this mean that these 2 methods will run for ever
CheckingRotaryEncoder();
}
//CheckingButtons() function will check the state of the buttons
void CheckingButtons() {
if (ButtonBox.getKeys()){
for (int i=0; i<LIST_MAX; i++) { //LIST_MAX is a variabe created in keypad.ccp and keypad.h
if ( ButtonBox.key[i].stateChanged ) { //this mean if the button has been pressed/hold or released
switch (ButtonBox.key[i].kstate) {
case PRESSED: digitalWrite(0,HIGH); //if the button is pressed and/or hold
case HOLD:
digitalWrite(0,HIGH);
break;
case RELEASED: digitalWrite(0,LOW); //if the button is idle or released
case IDLE:
break;
}
}
}
}
}
void initializeRotaryEncoders() { //create and initial rotary
for (int i=0;i<numOfRotaries;i++) {
pinMode(rotariesEncoders[i].pin1, INPUT); //set pins to input
pinMode(rotariesEncoders[i].pin2, INPUT);
#ifdef enablePullUps
digitalWrite(rotariesEncoders[i].pin1, HIGH); //set pins value to high
digitalWrite(rotariesEncoders[i].pin2, HIGH);
#endif
}
}
//Create and check pin state
unsigned char rotaryProcess(int i) {
unsigned char pinState = (digitalRead(rotariesEncoders[i].pin2) << 1)
| digitalRead(rotariesEncoders[i].pin1); //get the pins state
rotariesEncoders[i].state = rotaryTable[rotariesEncoders[i].state //determine a new state
& 0xf][pinState];
return (rotariesEncoders[i].state & 0x30); //return the created event
}
//check all rotaries encoder
void CheckingRotaryEncoder() {
for (int i=0;i<numOfRotaries;i++) {
unsigned char result = rotaryProcess(i);
if (result == DIR_CCW) { //if the rotary has been turned to left
digitalWrite(0,HIGH);
delay(250); //waiting 250ms = 1/4 second before set the value to 0
digitalWrite(0,LOW);
}
if (result == DIR_CW) { //if the rotary is turned to the right
digitalWrite(0,HIGH);
delay(250);
digitalWrite(0,LOW);
}
}
}