Following program causes controller (Uno) reset whenever the rotary encoder is rotated.
Register manipulation is used to get pins 6 (clock) and pin 7 (data) to invoke an interrupt routine ISR(PCINT0_VECT).
The purpose of the program is to move a stepper inline with rotary encoder revolutions.
What is wrong?
#include <AccelStepper.h>
#define MotorInterfaceType 4 // type 4 = unipolar motor controlled by 4 transistors ie ULN9003
#define MP1 8 // IN1 on the ULN2003
#define MP2 9 // IN2 on the ULN2003
#define MP3 10 // IN3 on the ULN2003
#define MP4 11 // IN4 on the ULN2003
#define ledIR 6 // input for IR led detector
// Rotary Encoder Inputs
#define clk 6 //Clock pin connected to D6
#define data 7 //Data pin connected to D7
#define btn 5 //Push button pin connected to D5
AccelStepper myStepper(MotorInterfaceType, MP1, MP3, MP2, MP4); //Define the pin sequence (IN1-IN3-IN2-IN4)
float rcvdSpeed, rcvdAccel;
long int rcvdDistance;
int counter = 0; //Use this variable to store "steps"
int previous_counter = 0; //Use this variable to store previous "steps" value
int currentStateClock; //Store the status of the clock pin (HIGH or LOW)
int StateData; //Store the status of the data pin (HIGH or LOW)
int lastStateClock; //Store the PREVIOUS status of the clock pin (HIGH or LOW)
String currentDir = ""; //Use this to print text
unsigned long lastButtonPress = 0; //Use this to store if the push button was pressed or not
uint16_t aState, aLastState; //GPIO #4-DT on encoder (Output B)
void setup() {
Serial.begin(9600);
delay(500);
Serial.println("DCCpp_turntable_controller_v2");
// set the maximum speed, acceleration factor,
// initial speed and the target position
myStepper.setMaxSpeed(1000.0);
myStepper.setAcceleration(30.0);
myStepper.setSpeed(200.0);
// myStepper.moveTo(2000);
myStepper.disableOutputs();
Serial.println(" output disabled ");
pinMode(clk, INPUT_PULLUP);
pinMode(data, INPUT_PULLUP);
aLastState = digitalRead(clk);
//Here we activate pin change interruptions on pin D8 and D9 with PCINT0 and PCINT1
PCICR |= (1 << PCIE2); // set PCICR register bit 2 (PCIE2: PCINT[23:16], 0B00000100
PCMSK2 |= (1 << PCINT22); // pin 6 PCINT22, 0B01000000
PCMSK2 |= (1 << PCINT23); // pin 7 PCINT23, 0B10000000
// Read the initial state of Clock pin (it could be HIGH or LOW)
lastStateClock = digitalRead(clk);
}
void loop() {
if (counter != previous_counter)
{
Serial.print("Counter: ");
Serial.println(counter);
}
delay(1);
runStepper(counter);
}
void runStepper(int ctr)
{
myStepper.enableOutputs(); //enable pins
myStepper.moveTo(ctr); //-1 is to match the rotation of the encoder with the rotation of the stepper
while (myStepper.distanceToGo() != 0)
{
myStepper.runToNewPosition(ctr);
}
}
/*In this case, the counter will automatically change its value in the interruption.
So all we need to do is to print its value in the void loop*/
ISR(PCINT0_vect) {
cli(); //We pause interrupts happening before we read pin values
currentStateClock = (PIND & 0B01000000); //Check pin D6 state? Clock
StateData = (PIND & 0B10000000); //Check pin D7 state? Data
if (currentStateClock != lastStateClock) {
// If "clock" state is different "data" state, the encoder is rotating clockwise
if (StateData != currentStateClock) {
counter ++; // We increment
}
//Else, the encoder is rotating counter-clockwise
else {
counter --; // We decrement
}
lastStateClock = currentStateClock; // Updates the previous state of the clock with the current state
sei(); //restart interrupts
}
}