/*Simple sketch to demonstrate using the TM1637 display and a rotation encoder
based on code from Ralph Bacon https://github.com/RalphBacon/226-Better-Rotary-Encoder---no-switch-bounce
and from Marko Pinteric (https://www.pinteric.com/mped.html
using the interrupt pins to avoid bounce
Note on the UNO this circuit requires both interrupt pins to be used
which leaves no other options for other hardware interrupts
*/
//add the display library
#include <TM1637Display.h>
//set up display
// Define the connections pins for display:
#define CLOCKA 7
#define DIOA 8
//power encoder, for test circuit
#define VROT1 12
// Create display object of type TM1637Display:
//so it turns out that adding an optional delay allows the display to work without affecting interrupts
TM1637Display displaya = TM1637Display(CLOCKA, DIOA, 11);
int bright=1;
//configure the rot encoder
#include <Arduino.h>
// Rotary encoder pins
//Note I had tried to use more than one
//Pins 2 and 3 are the only interrupt pins, it is therefore not possible to use more than one rotary encoder as it requires botgh interrupts
#define PIN_A 2
#define PIN_B 3
#define PUSH_BTN 4
// A turn counter for the rotary encoder (negative = anti-clockwise)
int rotationCounter = 0; //start count at zero
// Flag from interrupt routine (moved=true)
volatile bool rotaryEncoder = false;
// Interrupt routine just sets a flag when rotation is detected
void rotary()
{
rotaryEncoder = true;
}
// Rotary encoder has moved (interrupt tells us) but what happened?
// See https://www.pinteric.com/rotary.html
int8_t checkRotaryEncoder()
{
// Reset the flag that brought us here (from ISR)
rotaryEncoder = false;
static uint8_t lrmem = 3;
static int lrsum = 0;
static int8_t TRANS[] = {0, -1, 1, 14, 1, 0, 14, -1, -1, 14, 0, 1, 14, 1, -1, 0};
// Read BOTH pin states to deterimine validity of rotation (ie not just switch bounce)
int8_t l = digitalRead(PIN_A);
int8_t r = digitalRead(PIN_B);
// Move previous value 2 bits to the left and add in our new values
lrmem = ((lrmem & 0x03) << 2) + 2 * l + r;
// Convert the bit pattern to a movement indicator (14 = impossible, ie switch bounce)
lrsum += TRANS[lrmem];
/* encoder not in the neutral (detent) state */
if (lrsum % 4 != 0)
{
return 0;
}
/* encoder in the neutral state - clockwise rotation*/
if (lrsum == 4)
{
lrsum = 0;
return 1;
}
/* encoder in the neutral state - anti-clockwise rotation*/
if (lrsum == -4)
{
lrsum = 0;
return -1;
}
// An impossible rotation has been detected - ignore the movement
lrsum = 0;
return 0;
}
void setup() {
Serial.begin(115200);
//for displaya
pinMode(CLOCKA, OUTPUT);
pinMode(DIOA, OUTPUT);
//power pins for the rotary encoders
//not this is just for the test rig, they will be connected to VCC in final
pinMode(VROT1, OUTPUT);
//turn on the encoder
digitalWrite(VROT1, HIGH);
displaya.setBrightness(bright);
//display INFO
displaya.showNumberDec(-1);
// The module already has pullup resistors on board.
pinMode(PIN_A, INPUT);
pinMode(PIN_B, INPUT);
// But not for the push switch
pinMode(PUSH_BTN, INPUT_PULLUP);
// We need to monitor both pins, rising and falling for all states
attachInterrupt(digitalPinToInterrupt(PIN_A), rotary, CHANGE);
attachInterrupt(digitalPinToInterrupt(PIN_B), rotary, CHANGE);
Serial.println("Setup completed");
displaya.showNumberDec(0);
}
//main routine
void loop()
{
// Has rotary encoder moved?
if (rotaryEncoder)
{
// Get the movement (if valid)
int8_t rotationValue = checkRotaryEncoder();
// If valid movement, do something
if (rotationValue != 0)
{
rotationCounter += rotationValue * 1;
Serial.print(rotationValue < 1 ? "L:" : "R:");
Serial.println(rotationCounter);
if(rotationCounter<=7 & rotationCounter>=0){
//Set the brightness of the display 0 to 7
displaya.setBrightness(rotationCounter);
}
displaya.showNumberDec(rotationCounter);
}
}
if (digitalRead(PUSH_BTN) == LOW)
{
rotationCounter = 0;
Serial.print("B:");
Serial.println(rotationCounter);
displaya.showNumberDec(rotationCounter);
//don't repeat for 500 miliseconds
delay(500);
}
}