stm car HAL library speed measurement PID speed regulation Bluetooth OLED use

//Redirect serial port one
int fputc(int ch,FILE *stream)
{
HAL_UART_Transmit( & amp;huart1,( uint8_t *) & amp;ch,1,0xFFFF);
return ch;
}

//typedef struct __FILE FILE; When using printf, add #include<stdio.h>;
2. Serial port interrupt callback function
uint8_t g_ucUsart3ReceiveData; //Save the data received by serial port 3 main.c

HAL_UART_Receive_IT( & amp;huart3, & amp;g_ucUsart3ReceiveData,1); //Serial port three receives data and is opened in main.c


//Reimplement the serial port interrupt callback function in it.c
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == & amp;huart3)//Determine the interrupt source
{
if(g_ucUsart3ReceiveData == 'A') motorPidSetSpeed(1,1);//Previous motion

HAL_UART_Receive_IT( & amp;huart3, & amp;g_ucUsart3ReceiveData, 1);//Continue interrupt reception

}
}


//Declare external variables in usart.c
extern uint8_t g_ucUsart3ReceiveData; //Save the data received by serial port 3

3.pwm

HAL_TIM_PWM_Start( & amp;htim1,TIM_CHANNEL_1); // Turn on timer 1 channel 1 PWM output
HAL_TIM_PWM_Start( & amp;htim1,TIM_CHANNEL_4); // Turn on timer 1 channel 4 PWM output


__HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_1, 40);//Modify duty cycle

4. Level configuration

HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET);//Set AIN1 PB13 to low level
HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_SET); //Set BIN1 PB3 to high level
HAL_Delay(1000);
//Twice will cause the motor to reverse direction.
HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_SET);//Set AIN1 PB13 to high level
HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET); //Set BIN1 PB3 to low level

5. Motor

//Anti-redefinition function
#ifndef MOTOR_H__
#define MOTOP_H__


#endif




//Define macros to facilitate transplantation
#define AIN1_RESET HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET)//Set
Set AIN1 PB13 to low level
#define AIN1_SET HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_SET)//Set
AIN1 PB13 is high level
#define BIN1_RESET HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET)
//Set BIN1 PB3 to low level
#define BIN1_SET HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_SET)//Set
AIN1 PB13 is high level


//How the motor works
void Motor_Set (int motor1,int motor2)
{
//Set the selection direction according to the positive and negative parameters
if(motor1 < 0) BIN1_SET;
else BIN1_RESET;
if(motor2 < 0) AIN1_SET;
else AIN1_RESET;
//motor1 sets the speed of motor B
if(motor1 < 0)
{
if(motor1 < -99) motor1 = -99;//Exceeds PWM amplitude
//When it is negative, the smaller the absolute value, the larger the PWM duty cycle.
//Current motor1 -1 -99
//Give register or function 99 1
__HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_1, (100 + motor1));//Modify timer 1
Channel 1 PA8 Pulse changes duty cycle
}
else{
if(motor1 > 99) motor1 = 99;
//Now it is 0 1 99
//We assign the value 0 1 99
__HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_1, motor1);//Modify timer 1 channel 1
PA8 Pulse changes duty cycle
}
//motor2 sets the speed of motor A
if(motor2 < 0)
{
if(motor2 < -99) motor2 = -99;//Exceeds PWM amplitude
//When it is negative, the smaller the absolute value is, the larger the PWM duty cycle is.
//Current motor2 -1 -99
//Give register or function 99 1
__HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_4, (100 + motor2));//Modify timer 1 pass
Channel 4 PA11 Pulse changes the duty cycle
}
else{
if(motor2 > 99) motor2 = 99;
//Now it is 0 1 99
//We assign the value 0 1 99
__HAL_TIM_SET_COMPARE( & amp;htim1, TIM_CHANNEL_4, motor2);//Modify timer 1 channel 4
PA11 Pulse changes duty cycle
}
}

6.OLED:

The two pins of OLED

7. Enable timer and scheduled interrupt for encoder speed measurement

HAL_TIM_Encoder_Start( & amp;htim2,TIM_CHANNEL_ALL);//Start timer 2 encoder speed measurement
HAL_TIM_Encoder_Start( & amp;htim4,TIM_CHANNEL_ALL);//Start timer 4
HAL_TIM_Base_Start_IT( & amp;htim2); //Enable timer 2 interrupt
HAL_TIM_Base_Start_IT( & amp;htim4); //Enable timer 4 interrupt

HAL_TIM_Base_Start_IT( & amp;htim1); //Enable timer 1 interrupt


//Defined variables placed in stm32f1xx_it.c
short Encode1Count = 0;//
short Encode2Count = 0;
float Motor1Speed = 0.00;
float Motor2Speed = 0.00;
uint16_t TimerCount=0;

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        if(htim == & amp;htim1)//htim1 500HZ 2ms interrupt once
        {
            TimerCount + + ;
            if(TimerCount %5 == 0)//Execute once every 10ms
                {
                    Encode1Count = (short)__HAL_TIM_GET_COUNTER( & amp;htim4);
                    Encode2Count = (short)__HAL_TIM_GET_COUNTER( & amp;htim2);
                    __HAL_TIM_SET_COUNTER( & amp;htim4,0);
                    __HAL_TIM_SET_COUNTER( & amp;htim2,0);
                    Motor1Speed = (float)Encode1Count*100/9.6/11/4;
                    Motor2Speed = (float)Encode2Count*100/9.6/11/4;
                    TimerCount=0;
                 }
         }
}

8. Redirect fputc

int fputc(int ch,FILE *stream)
{
HAL_UART_Transmit( & amp;huart1,( uint8_t *) & amp;ch,1,0xFFFF);
return ch;
}

9.Bluetooth control speed

extern uint8_t g_ucUsart3ReceiveData; //Save the data received by serial port 3
int InitSpeed = 50;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == & amp;huart3)
{
if(g_ucUsart3ReceiveData == 'U')
{
InitSpeed + = 5;
if(InitSpeed >= 100) InitSpeed=100;
MotorGo(InitSpeed);
}
if(g_ucUsart3ReceiveData == 'D')
{
InitSpeed -= 5;
if(InitSpeed <= 0) InitSpeed=0;
MotorGo(InitSpeed);
}
HAL_UART_Receive_IT( & amp;huart3, & amp;g_ucUsart3ReceiveData, 1);//Continue interrupt reception
}
\t
}

10.pid parameter adjustment:

//in the .h file
#ifndef __PID_H
#define __PID_H
//Declare a structure type
typedef struct
{
float target_val;//target value
float actual_val;//actual value
float err;//Current deviation
float err_last;//Last deviation
float err_sum;//Error cumulative value
float Kp,Ki,Kd;//proportion, integral, differential coefficient
} tPid;
//Declare function
float P_realize(tPid * pid, float actual_val);
void PID_init(void);
float PI_realize(tPid * pid, float actual_val);
float PID_realize(tPid * pid, float actual_val);
#endif

//.c file
#include "pid.h"
//Define a structure type variable
tPid pidMotor1Speed;
//Assign initial value to structure type variable
void PID_init()
{
pidMotor1Speed.actual_val=0.0;
pidMotor1Speed.target_val=5;
pidMotor1Speed.err=0.0;
pidMotor1Speed.err_last=0.0;
pidMotor1Speed.err_sum=0.0;
pidMotor1Speed.Kp=10;
pidMotor1Speed.Ki=5;
pidMotor1Speed.Kd=0;
}


//PID control function
float PID_realize(tPid * pid, float actual_val)
{
pid->actual_val = actual_val;//Pass the real value
pid->err = pid->target_val - pid->actual_val; current error = target value - actual value
pid->err_sum + = pid->err;//Error cumulative value = current error cumulative sum
//Use PID control output = Kp*current error + Ki*accumulated error value + Kd*(current error-last error)
pid->actual_val = pid->Kp*pid->err + pid->Ki*pid->err_sum + pid->Kd*(pid->err - pid->err_last);
//Save the last error: assign this error to the last error
pid->err_last = pid->err;
return pid->actual_val;
}


//In the interrupt function
if(TimeCount ==0)//Every 20ms
{
MotorGo(PID_realize( & amp;pidMotor1Speed,MotorSpeed));
TimeCount=0;
}
extern tPid pidMotor1Speed;//Declare structure variables
PID_init();//Initialization in .c file