许戈. 2024-04-07 19:54 采纳率: 25%
浏览 5

pid控制编码器电机无法转动

库函数

 int cnt;
    int main(void)
    {
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      LED_Init();
        TIM3_PWM_Init(7199,0);//电机
      TIM4_PWM_init(199,719);//舵机
        hcsro4_init();
        encoder_init();
        uart_init(115200);
        tongxing_init();
         TIM2_Int_Init(99,7199);
         cnt=read_encodera();
  
        while(1)
        {    
            
   send_data(cnt);
}
        }


```c

void TIM3_PWM_Init(u16 arr,u16 psc)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;            
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        
    GPIO_Init(GPIOA, &GPIO_InitStructure);                     
    GPIO_ResetBits(GPIOA,GPIO_Pin_0);                    
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         
    GPIO_Init(GPIOA, &GPIO_InitStructure);                
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);                        
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         
    GPIO_Init(GPIOA, &GPIO_InitStructure);                     
    GPIO_ResetBits(GPIOA,GPIO_Pin_4);                        
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         
    GPIO_Init(GPIOA, &GPIO_InitStructure);                     
    GPIO_ResetBits(GPIOA,GPIO_Pin_5);                        
 
    TIM_TimeBaseStructure.TIM_Period = arr; 
    TIM_TimeBaseStructure.TIM_Prescaler =psc; 
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
        
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);  
 
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 
     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);  
  TIM_OC2Init(TIM3, &TIM_OCInitStructure);  
  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    TIM_Cmd(TIM3, ENABLE);  
 
}

void qianhou(float distance)
{
    if(distance>0){
    Ina=1;
    Inb=0;    
    Inc=1;
    Ind=0;
    TIM_SetCompare1(TIM3,distance);
        TIM_SetCompare2(TIM3,distance);
    }
    if(distance<0)
{
 
    Ina=0;
    Inb=1;
    Inc=0;
    Ind=1;
TIM_SetCompare1(TIM3,-distance);
TIM_SetCompare2(TIM3,-distance);    
}
}

```c
int pwm_turn(int a)
{
    int temp;
if(a<0)temp=-a;
    else temp=a;
return temp;
}
float v_real=0;
float kp=5;
float ki=0.0;
float kd=0.5;
int err_now=0;//现在误差
int err_last=0;
int err_last_last=0;
int spd_now=0;//速度
int err_i=0;//误差积分值
int jiaua =0;//
int out=0;
int16_t PID(float val,int target)
{
  //位置
    spd_now=pwm_turn(val);
    err_now=target-spd_now;
    err_i+=err_now;
    if (err_i>90) err_i=90;//限幅
    out=kp*err_now+ki*err_i+kd*(err_now-err_last);
    if(out>199) out=199;//pwm最大值不能超过
    if(out<-199) out=-199;
    err_last=err_now;
    //增量式
//    spd_now=cnt;
//  err_now=target-spd_now;
//    jiaua=kp*(err_now-err_last)+ki*err_now+kd*(err_now+err_last_last-2*err_last);
//    out+=jiaua;
//    if(out>900) out=900;
//    TIM_SetCompare1(TIM3,out);
//    err_last_last=err_last;
//    err_last=err_now;
return out;
}

```c
void encoder_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICINITStructInit;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;            
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;     
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);                     
                
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;    
    GPIO_Init(GPIOB, &GPIO_InitStructure);                
                    
    TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;          
    TIM_TimeBaseStructure.TIM_Prescaler =ENCODER_TIM_PSC; 
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
    TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
        
  
    TIM_ICStructInit(&TIM_ICINITStructInit);
    TIM_ICINITStructInit.TIM_ICFilter=0xF;
    TIM_ICINITStructInit.TIM_Channel=TIM_Channel_1;
    TIM_ICInit(TIM4,&TIM_ICINITStructInit);
    TIM_ICINITStructInit.TIM_ICFilter=0xF;
    TIM_ICINITStructInit.TIM_Channel=TIM_Channel_2;
    TIM_ICInit(TIM4,&TIM_ICINITStructInit);
    TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
        TIM_SetCounter(TIM4,0);
    TIM_Cmd(TIM4, ENABLE);
}
void TIM4_IRQHandler(void)
{
 if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update)==SET)//溢出中断
 {
     TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //清除中断标志位 
 }
}
 int16_t read_encodera(void)
{
    uint32_t encoderNum = 0;
    encoderNum = TIM_GetCounter(TIM4);
    
    //encoderNum=(encoderNum/4)/1320/0.1;//单位转每秒
    return encoderNum;
}
void TIM2_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    TIM_TimeBaseInitStruct.TIM_Period = arr;     //重装载值
    TIM_TimeBaseInitStruct.TIM_Prescaler = psc;  //预分频系数
    TIM_TimeBaseInitStruct.TIM_ClockDivision =0; //时钟分割
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
    
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  //使能定时器中断
    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;   //使能外部中断通道
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;   //使能外部中断通道
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;    //响应优先级3
    NVIC_Init(&NVIC_InitStruct);

    TIM_Cmd(TIM2,ENABLE);      
}
void TIM2_TRQHANDLER(void)
{
if (TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
int cnt=read_encodera();
    int target=1000;
    int out=PID(cnt,target);
    qianhou(out);
}
}




```

  • 写回答

5条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-07 19:54
    关注

    引自免费微信小程序:皆我百晓生

    好的,我将尽力回答您的问题。首先,让我们从PWM初始化开始。

    在程序开始之前,我们需要定义变量并配置它们的权限级别。我们将使用GPIO_Init()函数初始化GPIOA的几个引脚。由于我们正在使用模拟电路,因此我们可以忽略必需设置标志,并且不进行内联的PinModeProtocols更改。然后,我们将为GPIOA的7、8、10三个引脚指定基地址。

    接下来是TIM3初始化,包括配置TIM3作为定时器3,通过TIM_TimeBaseInit()函数设置时钟周期(在上面的代码中,我们将其设置为7199)和波特率(在下面的代码中,我们将使用115200)。我们还需要配置TIM3的一些基本寄存器选项,例如错误检测,计数器初始值和阈值等。

    接着,我们使用TIM3_PWM_Init()函数初始化PWM,这个函数接受一个参数数组作为参数,其中包含四个数字,分别表示电压与频率之间的比例。我们将这个数组的大小设置为参数的总和。我们也设置了低功耗模式(CMODE一直都是ON),并且不更新计数值,以便保持硬件状态。

    然后,我们使用TIM4_PWM_Init()函数初始化PWM,同样接受一个参数数组作为参数,但CMODE被设置为ON。同样地,我们会关闭它的同步功能,同时设置它为低功耗模式,以及清除计数值,以便保持硬件状态。

    接下来是HCSR初始化,这是用于处理CPS值的寄存器。在这个例子中,我们没有特别设置任何寄存器。但是,如果我们想要使用,只需将其赋值为适当的值即可。

    然后,我们初始化编码器和舵机,这里不需要设置更多复杂的功能。对于编码器,我们需要初始化s编码器 初始化()函数。对于舵机,我们需要初始化t编码器初始化()函数。

    然后,我们初始化TCXO初始化,这是一个用于电子门控信号转换器的寄存器。在这里,我们将清零其值。

    接下来是TI2和TI12的中断,这两个中断都需要配置相应的向量结构体。TI2的中断位于内部,并设置了对应的NVIC_InitStructure寄存器,这使得它可以更容易地管理中断。TI12的中断位于外部,所以我们需要设置NVIC_InitStructure寄存器来允许外部中断。在这里,我们只需要配置错误检测、计数器和复位。

    接下来是驱动器接口初始化,这里我们需要配置其TIM_EncoderInterfaceConfig()函数,以启用带优先级的定时器扩展。我们需要设置一个延迟(PSC),这意味着当计数器达到一定值后,将以高于预定的速度计数。

    最后,我们设置TIM_Cmd()函数来使这些定时器接口可以触发定时器事件。

    现在,我们可以测试这些定时器初始化函数了。使用send_data()函数发送数据,这样就可以检查所有延迟是否正确设置和工作。如果没有发生任何问题,那么这表明所有的定时器都已经成功初始化了。

    如果你有任何其他问题,或者想要更详细的解释,欢迎随时提问。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月7日

悬赏问题

  • ¥30 c#打开word开启修订并实时显示批注
  • ¥15 如何解决ldsc的这条报错/index error
  • ¥15 VS2022+WDK驱动开发环境
  • ¥30 关于#java#的问题,请各位专家解答!
  • ¥30 vue+element根据数据循环生成多个table,如何实现最后一列 平均分合并
  • ¥20 pcf8563时钟芯片不启振
  • ¥20 pip2.40更新pip2.43时报错
  • ¥15 换yum源但仍然用不了httpd
  • ¥50 C# 使用DEVMOD设置打印机首选项
  • ¥15 麒麟V10 arm安装gdal