const int EncoderPin1 = 7 ; //set the encoder pin A const int EncoderPin2 = 6; //set the encoder pin B int encoderPin2Value = 0 ; //store the encoder value volatile int motorPosition = 0 ; // the initial position of the motor float previousmotorPosition = -1 ; // the previous motor position int MotorDirection ; // store the direction int RotaryCLK = 5 ; // the CLK pin of the rotary encoder or OUTPUT A int RotaryDT = 4 ; // the DT pin or the OUTPUT B int RotarySW = 3 ; // the button pin of the rotary encoder int SW_buttonValue = 0; // storing the button value int RotaryValue ; // value manupilated by the encoder int RotaryTime ; // store the time of that need the encoder volatile int encoderPosition = 0 ; // the initial encoder position float encoderPreviousPosition = -1 ; // store the last position of the encoder int RightDirectionPin = 12 ; //define the in1 int LeftDirectionPin = 11 ; //define the in2 int CLKNow ; // the information came from the rotary_clk int CLKPrevious ; int DTNow ; // the information came from the rotary_DT int DTPrevious ; int TargetPosition ; // the position of the target to reach float currentTime = millis(); // the current time on millis() float previousTime ; float errorValue ; // store the error value float previousError ; float error ; // the error or motorPosition - targetPosition float controlSignal = 0; // Also called as process variable (PV) //PID parameters - tuned by the user double kp = 1.35 ; double ki = 0.00005; double kd = 0.01; void setup() { Serial.begin(115200); pinMode(EncoderPin1,INPUT); pinMode(EncoderPin2,INPUT); attachInterrupt(digitalPinToInterrupt(EncoderPin1),CheckEncoder,RISING); pinMode(RightDirectionPin,OUTPUT); pinMode(LeftDirectionPin,OUTPUT); pinMode( RotaryCLK,INPUT_PULLUP); pinMode( RotaryDT,INPUT_PULLUP); pinMode( RotarySW,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(EncoderPin2),RotaryEncoder,CHANGE); // store states CLKPrevious = digitalRead(RotaryCLK); DTPrevious = digitalRead(RotaryDT); } void loop() { calculatePID(); DriveMotor(); CheckRotaryButton(); } void CheckEncoder(){ encoderPin2Value = digitalRead(EncoderPin2); if(encoderPin2Value == 1) //cw { motorPosition++ ; } else if(encoderPin2Value == 0) //ccw { motorPosition-- ; } } void DriveMotor(){ if(controlSignal < 0){ MotorDirection = -1 ; // go left } else if(controlSignal >0) { MotorDirection = 1 ; // go right } else { MotorDirection = 0 ; // stop } if(MotorDirection == -1) { digitalWrite(RightDirectionPin,LOW); digitalWrite(LeftDirectionPin,HIGH); } else if(MotorDirection == 1){ digitalWrite(RightDirectionPin,HIGH); digitalWrite(LeftDirectionPin,LOW); } else{ digitalWrite(RightDirectionPin,LOW); digitalWrite(LeftDirectionPin,LOW); } } void calculatePID() // the PID calculation or proportional-integral-direvative { int DeltaTime = (currentTime - previousTime )/ 1000000 ; // change the result of dt to seconds currentTime = previousTime ; errorValue = motorPosition - TargetPosition ; // calculate the error value double proportionnel = error ; double integrale =+ error * ki; double direvative = (error-previousError ); previousError = error ; // save the error errorValue = (proportionnel*kp)+(integrale*ki)+(direvative*kd); // here the pid is calculated } void RotaryEncoder(){ CLKNow = digitalRead(RotaryCLK); if(CLKNow != CLKPrevious && CLKNow == 1) { if(RotaryDT != CLKNow) // ccw { RotaryValue = RotaryValue - 515 ; // go left or ccw } else //cw { RotaryValue = RotaryValue + 515 ; // the disk on the motor turn right 515 tour to reach a turn of the axe } } CLKNow = CLKPrevious ; } void CheckRotaryButton() { SW_buttonValue = digitalRead(RotarySW); if(SW_buttonValue == 0) // it depend on the wiring of the rotary encoder { if(millis() - RotaryTime > 1000){ TargetPosition = RotaryValue ; RotaryTime = millis(); // save time } } } // created by BL.MK