stm32f103c8t6倒立摆自动起摆使用标准库使用角度传感器WDD35D驱动AT8236代码
时间: 2023-10-01 11:07:28 浏览: 137
以下是一个简单的使用标准库驱动WDD35D角度传感器和AT8236电机驱动的倒立摆自动起摆的示例代码:
```
#include "stm32f10x.h"
#define MOTOR_PIN GPIO_Pin_8
#define MOTOR_GPIO GPIOB
#define MOTOR_RCC RCC_APB2Periph_GPIOB
#define MOTOR_TIM TIM4
#define MOTOR_TIM_RCC RCC_APB1Periph_TIM4
#define MOTOR_PERIOD (72000000 / 20000) // 20kHz PWM
#define ANGLE_PIN GPIO_Pin_0
#define ANGLE_GPIO GPIOA
#define ANGLE_RCC RCC_APB2Periph_GPIOA
#define ANGLE_ADC ADC1
#define ANGLE_CHANNEL ADC_Channel_0
#define ANGLE_SAMPLES 16
#define KP 50.0f
#define KI 0.1f
#define KD 0.1f
#define DT 0.001f
int16_t angle = 0;
int16_t angle_error = 0;
int16_t angle_error_integral = 0;
int16_t angle_error_derivative = 0;
int16_t angle_error_previous = 0;
void motor_init() {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(MOTOR_RCC, ENABLE);
RCC_APB1PeriphClockCmd(MOTOR_TIM_RCC, ENABLE);
GPIO_InitStructure.GPIO_Pin = MOTOR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(MOTOR_GPIO, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = MOTOR_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(MOTOR_TIM, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(MOTOR_TIM, &TIM_OCInitStructure);
TIM_Cmd(MOTOR_TIM, ENABLE);
TIM_CtrlPWMOutputs(MOTOR_TIM, ENABLE);
}
void angle_init() {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(ANGLE_RCC, ENABLE);
GPIO_InitStructure.GPIO_Pin = ANGLE_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(ANGLE_GPIO, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ANGLE_ADC, &ADC_InitStructure);
ADC_RegularChannelConfig(ANGLE_ADC, ANGLE_CHANNEL, 1, ADC_SampleTime_239Cycles5);
ADC_Cmd(ANGLE_ADC, ENABLE);
ADC_ResetCalibration(ANGLE_ADC);
while (ADC_GetResetCalibrationStatus(ANGLE_ADC))
;
ADC_StartCalibration(ANGLE_ADC);
while (ADC_GetCalibrationStatus(ANGLE_ADC))
;
}
int16_t angle_read() {
int i;
int32_t sum = 0;
for (i = 0; i < ANGLE_SAMPLES; i++) {
ADC_SoftwareStartConvCmd(ANGLE_ADC, ENABLE);
while (!ADC_GetFlagStatus(ANGLE_ADC, ADC_FLAG_EOC))
;
sum += ADC_GetConversionValue(ANGLE_ADC);
}
return (int16_t)(sum / ANGLE_SAMPLES);
}
void angle_control() {
angle = angle_read();
angle_error = angle - 90; // setpoint is 90 degrees
angle_error_integral += angle_error;
angle_error_derivative = angle_error - angle_error_previous;
angle_error_previous = angle_error;
int16_t pwm = KP * angle_error + KI * angle_error_integral * DT + KD * angle_error_derivative / DT;
TIM_SetCompare1(MOTOR_TIM, pwm);
}
int main(void) {
motor_init();
angle_init();
while (1) {
angle_control();
}
}
```
该代码使用了定时器 PWM 输出控制电机,ADC 读取角度传感器的值,PID 控制器计算电机的 PWM 值,以实现倒立摆自动起摆。其中,KP、KI 和 KD 分别为比例、积分和微分系数,DT 为采样时间。注意需根据具体硬件配置和参数调整代码。
阅读全文