stc8a–xunji—pid—-gongxundamow code

/********************************************** *******************************
* Routine name: empty project
* Note: New projects can directly copy empty projects to start programming.
* Wiring     : ---
* Notice    \t\t : ---
***************************************************** *******************************/

//--Include the header files you want to use--//
#include "config.h" //General configuration header file

#define LED_ON 0
#define LED_OFF 1

#define GYRO_OFFSET 13 //Gyroscope zero drift value

#define Car_speed 200 // car speed

#define VKp 8 //Car speed PID proportional coefficient
#define VKi 3 //Trolley speed PID integral coefficient
#define VKd 0 //Trolley speed PID differential coefficient

//--declare some constants to use--//
int Kp =1400; //The direction scale factor of the car's tracking is 1500
int Kd =15; //The directional damping coefficient of the car's tracking is 17

sbit LED0 = P4^4;
sbit LED1 = P5^4;

#define LED_DATA P6 //select digital tube segment
#define IR_LED P0 //IR sensor status

uchar IR_LR=0; //Infrared tube left and right sequence


uchar GX_n = 0; //crossing count variable=0

sbit W1 = P7^4; //digital tube selection control pin
sbit W2 = P7^5;
sbit W3 = P7^6;
sbit W4 = P7^7;

sbit KEY_UP = P4^0;
sbit KEY_DOWN = P4^1;
sbit KEY_LEFT = P4^2;
sbit KEY_RIGHT = P4^3;
sbit KEY = P3^2;

bit CAR_PWM_EN = 0; //PWM enable =0 not running =1 running

int L_speed =0; //wheel speed
int R_speed = 0;

int PWM_SPEED=0;//speed control PWM value
int PWM_DIR = 0;//direction control PWM value

int Set_Speed = Car_speed; //set speed

int Err_Speed = 0; //current deviation
int Err_Speed_Old = 0;//The last deviation
int Err_Speed_OldOld= 0;//The last 2 deviations

int L_PWM =0; //Define the PWM of the left and right wheels
int R_PWM = 0;

int Car_Err = 0 ; // car body deviation
int Car_Err_old = 0 ; //The last deviation of the car body

uint32 S_car =0; //The distance traveled by the car
uchar IRLED = 0;
uchar IRLED8[8] = {<!-- -->0};
uchar MPU6050_DATA[14];
float GYRO_Z;
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
uchar DIS_LED[]={<!-- -->0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x3e,0x38,0x73,0x49,0x78}; //segment code table
// 0 1 2 3 4 5 6 7 8 9 U L P S T
uchar DIS_LED_DATA[4] = {<!-- -->10,1,2,3}; //The data to be displayed by the four digital tubes
uchar KEY_OLD[5] = {<!-- -->0xff}; //The past state of the button
uchar L_n =0; //Ultrasonic data control bit
uchar L_data[3]; //ultrasonic data buffer
uint32 LL = 0; //The distance measured by ultrasonic wave

//--declare some variables that need to be used--//
uint T0_n =0; //timer 0 count variable
uint POWER_U_ADC; //battery voltage ADC value
uchar DIS_dat = 0; //DAT =0 - display voltage =1 - display speed =2 - display PWM value
uint CAR_SPEED = 123; //Define the car speed

void MOTOR_OUT(int Lpwm,int Rpwm); //motor PWM output function
void DIS_LEDS(void); // digital tube refresh function
void SCAN_KEY(void); //key scanning function
char Get_Err(uchar IR); //Get the car body deviation function
/**************************************************** *******************************
* Function name: main
* Function function: main function
* Input: None
* Output: none
***************************************************** *******************************/
void main(void)
{<!-- -->
int i=0;

GPIO_init_allpin(0); //Initialize all IOs as quasi-bidirectional
GPIO_init_pin(20,1); //Initialize the motor drive pin to strong push-pull mode
GPIO_init_pin(21,1);
GPIO_init_pin(22,1);
GPIO_init_pin(23,1);
GPIO_init_pin(55,1);
GPIO_init_8pin(6,1); //Initialize all IOs of P6 as strong push-pull
GPIO_init_pin(74,1); //Initialize the bit selection pin of the digital tube to strong push-pull mode
GPIO_init_pin(75,1);
GPIO_init_pin(76,1);
GPIO_init_pin(77,1);
GPIO_init_pin(17,2); //P17ADC pin high impedance mode
\t
UART_init(1,115200,1,1); //Initialize serial port 1, baud rate 115200bps, the first multiplex,
UART_init(3,9600,2,1); //Initialize the serial port 3, the baud rate is 9600bps, the second channel is multiplexed, and read the distance of the ultrasonic module
PIT_init_ms(2,10); //Initialize timer 2, 10ms interrupt
ADC_init(7,8,4); //Initialize ADC to measure battery voltage
PCA_Pwm_init(70,50,0); //Initialize the PCA module and generate 50HZPWM to control the steering gear
INT_init(2,0); //Initialize external interrupt 2.3
INT_init(3,0);
\t
InitMPU6050(); //Initialize the gyroscope module
\t
PWM_init(20,1000,0); //Initialize motor PWM pin
PWM_init(21,1000,0);
PWM_init(22,1000,0);
PWM_init(23,1000,0);
\t
BUZZ = 1; //buzzer sounds
Delay_X_mS(500);
BUZZ = 0;
\t
while (1)
{<!-- -->
SCAN_KEY(); //Scan keys
DIS_LEDS(); //Refresh digital tube
\t\t
// judge the starting line
if(S_car>2000) //Constraints for the first crossing line
{<!-- -->
if(LL > 50 & amp; & amp; LL < 300) // determine whether there is a roadblock
{<!-- -->
CAR_PWM_EN = 0;
while(LL < 300);
CAR_PWM_EN = 1;
PWM_SPEED = 0;
Err_Speed_Old=0;
Err_Speed=0;
}
\t\t\t
if(IR_LED == 0xFF & amp; & amp; GX_n == 0) //If the line is pressed
{<!-- -->
while(IR_LED == 0xFF); //wait for the line
GX_n = 1; //Enable cross-line variables
}
if(IR_LED == 0xFF & amp; & amp; GX_n != 0) //If the second press line
{<!-- -->
CAR_PWM_EN = 0;
}
}
}
}

void UART3_isr(void)
{<!-- -->
uchar DAT3;
\t
DAT3 = S3BUF; //Read the data received by serial port 3
\t
if(L_n <= 2) //save data
{<!-- -->
L_data[L_n] = DAT3;
L_n++;
}
\t
if(L_n >= 3) // when receiving is complete
{<!-- -->
LL = (L_data[0]*65536 + L_data[1]*256 + L_data[2])/1000; //Get the distance value
if(LL > 999) LL =999; // limit the distance
}
}

void INT2_isr(void) //collect the pulse of external interrupt 2 and judge the direction
{<!-- -->
if(P34) L_speed ++ ;
else L_speed--;
}
void INT3_isr(void) //collect the pulse of external interrupt 2 and judge the direction
{<!-- -->
if(P35) R_speed--;
else R_speed++;
}

void SCAN_KEY(void)
{<!-- -->
uchar key;
\t
KEY_OLD[0]<<=1; //Key state before iteration
KEY_OLD[1]<<=1;
KEY_OLD[2]<<=1;
KEY_OLD[3]<<=1;
KEY_OLD[4]<<=1;
key = KEY_UP;
KEY_OLD[0] + = key;
key = KEY_DOWN;
KEY_OLD[1] + = key;
key = KEY_LEFT;
KEY_OLD[2] + = key;
key = KEY_RIGHT;
KEY_OLD[3] + = key;
key = KEY;
KEY_OLD[4] + = key;
if(KEY_OLD[4] == 0x00) //Judge the middle button is pressed
{<!-- -->
while(!KEY); //wait for the button to be released
\t\t
switch(DIS_dat)
{<!-- -->
case 0:
{<!-- -->
CAR_PWM_EN =!CAR_PWM_EN; //Departure judgment
\t\t\t\t\t\t\t
S_car = 0;
PWM_SPEED = 0;
Err_Speed_Old=0;
Err_Speed=0;
\t\t\t\t\t\t\t
}break; //Interface 1
case 1: //Interface 2
{<!-- -->
}break;
case 2: //Interface 3
{<!-- -->
}break;
}
}
if(KEY_OLD[0] == 0x00) //Press when judging UP
{<!-- -->
while(!KEY_UP); //wait for the button to be released
\t\t
switch(DIS_dat)
{<!-- -->
case 0: //Interface 1
{<!-- -->
Set_Speed += 5;
\t\t\t\t\t\t\t
}break;
case 1: //Interface 2
{<!-- -->
}break;
case 2: //Interface 3
{<!-- -->
Kp + = 50;
}break;
case 3: //Interface 4
{<!-- -->
Kd + = 1;
}break;
}
}
if(KEY_OLD[1] == 0x00) //press when judging DOWN
{<!-- -->
while(!KEY_DOWN); //wait for the button to be released
\t\t
switch(DIS_dat)
{<!-- -->
case 0: //Interface 1
{<!-- -->
Set_Speed -= 5;
}break;
case 1:
{<!-- -->
}break;
case 2:
{<!-- -->
Kp -= 50;
}break;
case 3: //Interface 4
{<!-- -->
Kd -= 1;
}break;
}
}
if(KEY_OLD[2] == 0x00) //Press when judging LEFT
{<!-- -->
while(!KEY_LEFT); //Wait for the button to be released
\t\t
if(DIS_dat>0) DIS_dat-=1;
}
if(KEY_OLD[3] == 0x00) //Press when judging RIGHT
{<!-- -->
while(!KEY_RIGHT); //wait for the button to be released
\t\t
if(DIS_dat<4) DIS_dat + =1;
}
\t
}

char Get_Err(uchar IR)
{<!-- -->
char L,R,i;
\t
L = 0; //Look for rising edge from left to right
for(i=0;i<7;i ++ )
{<!-- -->
if(((IR & amp; 1<<(i + 1)) >> (i + 1))-((IR & amp; 1<<i) >> i) == 1) //left to right find rising edge
{<!-- -->
L = i;
break;
}
}
R = 7; //Right to left to find the rising edge
for(i=7;i>0;i--)
{<!-- -->
if(((IR & amp; 1<<(i)) >> (i))-((IR & amp; 1<<(i + 1)) >> (i + 1)) == 1) / /Left to right to find the rising edge
{<!-- -->
R = i;
break;
}
}
i = L + R - 7;
\t
return i;
}

void DIS_LEDS(void)
{<!-- -->
int i;
\t
switch(DIS_dat)
{<!-- -->
case 0: //display vehicle speed
{<!-- -->
DIS_LED_DATA[0] = 13; //S
DIS_LED_DATA[1] = Set_Speed/100;
DIS_LED_DATA[2] = Set_Speed/10;
DIS_LED_DATA[3] = Set_Speed/1;
break;
}
case 1: //display battery voltage
{<!-- -->
DIS_LED_DATA[0] = 10; //U
DIS_LED_DATA[1] = POWER_U_ADC/100;
DIS_LED_DATA[2] = POWER_U_ADC/10;
DIS_LED_DATA[3] = POWER_U_ADC/1;
break;
}
case 2: //Display KP
{<!-- -->
DIS_LED_DATA[0] = 12; //P
DIS_LED_DATA[1] = Kp/1000;
DIS_LED_DATA[2] = Kp/100;
DIS_LED_DATA[3] = Kp/10;
break;
}
case 3: //Display KD
{<!-- -->
DIS_LED_DATA[0] = 14; //d
DIS_LED_DATA[1] = Kd/100;
DIS_LED_DATA[2] = Kd/10;
DIS_LED_DATA[3] = Kd/1;
break;
}
case 4: //Display L
{<!-- -->
DIS_LED_DATA[0] = 11; //L
DIS_LED_DATA[1] = LL/100;
DIS_LED_DATA[2] = LL/10;
DIS_LED_DATA[3] = LL/1;
break;
}
}
\t
for(i=0;i<4;i ++ )
{<!-- -->
switch(i)
{<!-- -->
case 0:
{<!-- -->
W1 = 1;W2 = 0;W3 = 0;W4 = 0; //The first bit is on
LED_DATA = DIS_LED[DIS_LED_DATA[3]];
}break;
case 1:
{<!-- -->
W1 = 0;W2 = 1;W3 = 0;W4 = 0; //The second bit is on
LED_DATA = DIS_LED[DIS_LED_DATA[2]];
}break;
case 2:
{<!-- -->
W1 = 0;W2 = 0;W3 = 1;W4 = 0; //the third bit is on
if(DIS_dat == 1) //if display voltage + decimal point
{<!-- -->
LED_DATA = DIS_LED[DIS_LED_DATA[1]] | 0x80;
}
else
{<!-- -->
LED_DATA = DIS_LED[DIS_LED_DATA[1]];
}
}break;
case 3:
{<!-- -->
W1 = 0;W2 = 0;W3 = 0;W4 = 1; //The 4th bit is on
LED_DATA = DIS_LED[DIS_LED_DATA[0]];
}break;
}
Delay_X_mS(2);
LED_DATA = 0x00;
}
}

void MOTOR_OUT(int Lpwm, int Rpwm)
{<!-- -->
if(Lpwm>9600) Lpwm = 9600; //output PWM limiter
if(Rpwm>9600) Rpwm = 9600;
if(Lpwm<-9600) Lpwm = -9600;
if(Rpwm<-9600) Rpwm = -9600;
\t
if(Lpwm > 0) //judging the direction of the left wheel
{<!-- -->
PWM_change(20,abs(Lpwm)); //forward rotation
PWM_change(21,0);
}
else
{<!-- -->
PWM_change(20,0); //Reverse
PWM_change(21,abs(Lpwm));
}
\t
if(Rpwm > 0) //judging the direction of the right wheel
{<!-- -->
PWM_change(23,abs(Rpwm)); //forward rotation
PWM_change(22,0);
}
else
{<!-- -->
PWM_change(23,0); //Reverse
PWM_change(22,abs(Rpwm));
}
\t
}


void TM2_isr(void) //10ms one interrupt
{<!-- -->
\t
uchar a;
\t
if(T0_n<9999) T0_n ++ ; //Form a loop variable
else T0_n=0;
\t
\t
if(GX_n != 0 & amp; & amp; GX_n < 50)
{<!-- -->
GX_n ++ ; //The cross-line variable is added automatically
}
else if(GX_n == 50)
{<!-- -->
GX_n = 0;
}
\t\t
\t
Read_MPU6050(MPU6050_DATA); //Read gyroscope raw data
GYRO_Z = ((int)(MPU6050_DATA[12]<<8 | MPU6050_DATA[13]) + GYRO_OFFSET)/65.5; //Conversion data
\t
IR_LR = 0;
a= P07; //The rightmost infrared tube pin
IR_LR + = a*128;
a= P06;
IR_LR + = a*64;
a= P05;
IR_LR + = a*32;
a= P04;
IR_LR + = a*16;
a= P03;
IR_LR + = a*8;
a= P02;
IR_LR + = a*4;
a= P01;
IR_LR + = a*2;
a= P00; //The leftmost infrared tube pin
IR_LR + = a*1;
\t
Car_Err = Get_Err(IR_LR); //Read the status of the infrared tube and calculate the deviation p07 p06 p05 p04 - p00
\t
PWM_DIR = Car_Err * Kp + GYRO_Z * Kd ; //direction PID calculation
\t
\t
if(CAR_PWM_EN == 0 ) //Enable PWM output
{<!-- -->
Set_Speed = 0;
\t\t
//PWM_SPEED = 0;
//PWM_SPEED = 0;
}
else
{<!-- -->
Set_Speed = Car_speed;
}
\t
L_PWM = PWM_SPEED + PWM_DIR; //speed loop + direction loop
R_PWM = PWM_SPEED - PWM_DIR; //speed loop - direction loop
\t
Car_Err = IR_LR;
\t
if(Car_Err == 0x00) //Lost the line
{<!-- -->
if(Car_Err_old == 0x80)
{<!-- -->
MOTOR_OUT(5000,-1500); //motor open loop output control
while(!(P05)); //0010 0000
}
if(Car_Err_old == 0x01)
{<!-- -->
MOTOR_OUT(-1500,5000); //motor open loop output control
while(!(P02)); //0000 0100
}
}

Car_Err_old = Car_Err; //Iterate last state
\t
\t
\t
MOTOR_OUT(L_PWM,R_PWM); //motor open loop output control

if(T0_n % 5 == 0) //50ms speed control
{<!-- -->
Err_Speed = Set_Speed - (L_speed + R_speed); // get deviation speed
\t\t
S_car + = (L_speed + R_speed); //Integral car travel distance
\t\t
PWM_SPEED + = VKp * (Err_Speed - Err_Speed_Old) + VKi * (Err_Speed); //position type PID formula
\t\t
if(PWM_SPEED>5000) PWM_SPEED = 5000; //output limiter
if(PWM_SPEED<-5000) PWM_SPEED = -5000;
\t\t
Err_Speed_OldOld = Err_Speed_Old; //Deviation iteration
Err_Speed_Old = Err_Speed;
\t\t
L_speed = 0; //speed cleared to 0
R_speed = 0;
\t\t
if(CAR_PWM_EN == 1) //running
{<!-- -->
PCA_Pwm_change(0,780-(Get_Err(P0)*30)); //The servo looks ahead
}
else
{<!-- -->
PCA_Pwm_change(0,780); //Steering gear back to normal
}
}
\t\t
if(T0_n % == 0) //Execute once every 250ms
{<!-- -->
LED0=!LED0; //The light flashes
LED1=!LED1;
\t\t
\t\t
UART_Send_byte(3,0xA0); //Send start ranging data
L_n = 0;
\t\t
POWER_U_ADC = ADC_get(7); //Get the conversion result of ADC channel 7
POWER_U_ADC /= 4.09; //Convert the ADC value into battery voltage*100 times
}

}