Im trying to control position of carriage printer with Dc motor by entering the desired position from keypad.The PID code works perfectly without the keypad.but i want to enter the position from keypad.The main problem i think is storing the input number from keypad and then use the # key for PID calculation.
Thanks in advance.
Code:
#include <Keypad.h>
#include <LiquidCrystal.h>
long Number;
char key;
double count = 0; //set the counts of the encoder
double positie = 0;//set the position
boolean A,B;
byte state, statep;
double pwm = 5;// this is the PWM pin for the motor for how much we move it to correct for its error
const int dir1 = 6;//these pins are to control the direction of the motor (clockwise/counter-clockwise)
const int dir2 = 7;
//I am setting it to move through 100 degrees
double Kp = 0.32;// you can set these constants however you like depending on trial & error
double Ki = 0.1;
double Kd = 0.3;
float last_error = 0;
float error = 0;
float changeError = 0;
float totalError = 0;
float pidTerm = 0;
float pidTerm_scaled = 0;// if the total gain we get is not in the PWM range we scale it down so that it's not bigger than |255|
const byte ROWS = 4; //four row
const byte COLS = 3; //four column
//define the cymbols on the buttons of the keypads
char Keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[ROWS] = {28, 27, 26, 25}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {24, 23, 22 }; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
Keypad keypad = Keypad( makeKeymap(Keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
void setup(){
Serial.begin(9600);
lcd.print("SetPoint");
pinMode(2, INPUT);//encoder pins
pinMode(3, INPUT);
attachInterrupt(0,Achange,CHANGE);//interrupt pins for encoder
attachInterrupt(1,Bchange,CHANGE);
pinMode(pwm, OUTPUT);
pinMode(dir1, OUTPUT);
pinMode(dir2, OUTPUT);
Serial.println(count);
}
void loop() {
key = keypad.getKey(); //storing pressed key value in a char
if (key!=NO_KEY){
DetectButtons();
gotodistance();
}
}
void Achange() //these functions are for finding the encoder counts
{
A = digitalRead(2);
B = digitalRead(3);
if ((A==HIGH)&&(B==HIGH)) state = 1;
if ((A==HIGH)&&(B==LOW)) state = 2;
if ((A==LOW)&&(B==LOW)) state = 3;
if((A==LOW)&&(B==HIGH)) state = 4;
switch (state)
{
case 1:
{
if (statep == 2) count++;
if (statep == 4) count--;
break;
}
case 2:
{
if (statep == 1) count--;
if (statep == 3) count++;
break;
}
case 3:
{
if (statep == 2) count --;
if (statep == 4) count ++;
break;
}
default:
{
if (statep == 1) count++;
if (statep == 3) count--;
}
}
statep = state;
}
void Bchange()
{
A = digitalRead(2);
B = digitalRead(3);
if ((A==HIGH)&&(B==HIGH)) state = 1;
if ((A==HIGH)&&(B==LOW)) state = 2;
if ((A==LOW)&&(B==LOW)) state = 3;
if((A==LOW)&&(B==HIGH)) state = 4;
switch (state)
{
case 1:
{
if (statep == 2) count++;
if (statep == 4) count--;
break;
}
case 2:
{
if (statep == 1) count--;
if (statep == 3) count++;
break;
}
case 3:
{
if (statep == 2) count --;
if (statep == 4) count ++;
break;
}
default:
{
if (statep == 1) count++;
if (statep == 3) count--;
}
}
statep = state;
}
void DetectButtons()
{
if (key == '1') //If Button 1 is pressed
{
if (Number==0)
Number=1;
else
Number = (Number*10) + 1; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '4') //If Button 4 is pressed
{
if (Number==0)
Number=4;
else
Number = (Number*10) + 4; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '7') //If Button 7 is pressed
{
if (Number==0)
Number=7;
else
Number = (Number*10) + 7; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '0')
{
if (Number==0)
Number=0;
else
Number = (Number*10) + 0; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '2') //Button 2 is Pressed
{
if (Number==0)
Number=2;
else
Number = (Number*10) + 2; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '5')
{
if (Number==0)
Number=5;
else
Number = (Number*10) + 5; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '8')
{
if (Number==0)
Number=8;
else
Number = (Number*10) + 8; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '3')
{
if (Number==0)
Number=3;
else
Number = (Number*10) + 3; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '6')
{
if (Number==0)
Number=6;
else
Number = (Number*10) + 6; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
if (key == '9')
{
if (Number==0)
Number=9;
else
Number = (Number*10) + 9; //Pressed twice
Serial.println(Number);
lcd.print(Number);
}
}
void gotodistance()
{
if(key == '#')
{
PIDcalculation();// find PID value
if (positie < Number) {
digitalWrite(dir1, HIGH);// Forward motion
digitalWrite(dir2, LOW);
} else {
digitalWrite(dir1, LOW);//Reverse motion
digitalWrite(dir2, HIGH);
}
analogWrite(pwm, pidTerm_scaled);
}
}
void PIDcalculation(){
positie = (count/232);//count to position conversion
error = Number - positie;
changeError = error - last_error; // derivative term
totalError += error; //accumalate errors to find integral term
pidTerm = (Kp * error) + (Ki * totalError) + (Kd * changeError);//total gain
pidTerm = constrain(pidTerm, -250, 250);//constraining to appropriate value
pidTerm_scaled = abs(pidTerm);//make sure it's a positive value
last_error = error;
}