极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 34386|回复: 5

搞了半个月,搞不定小车走直线的问题,PID也调不了

[复制链接]
发表于 2016-4-22 12:43:14 | 显示全部楼层 |阅读模式
为了小车走个直线,我用了Arduino 的 PID_V1 库,  20 线的码盘测速,L298N 调速,把左右马达速度差(左边马达速度-右边马达速度)作为输入 Input ,采用 左边马达PWM +Output, 右边马达PWM-Output ,的计算方式, 在USB线连接Arduino板的时候 ,测试是比较正常的,

但是USB线拔掉,左边马达就直接停了!无论我怎么调PID 参数都没作用!!

我附上视频,在视频里, 如果 连接 USB 线, 按右边轮子减速,左边会跟着减速,按左边轮子,右边也同样的




拔掉USB线后,左边轮子很快就停止了!!


我的PID 参数设置D 为0 ,只调整 P 和 I,

我实在搞不懂是什么原因,难道是不需要积分I,而是要P和 D ?
回复

使用道具 举报

发表于 2016-4-22 13:52:08 | 显示全部楼层
看录像两个轮子都转啊!你问问题要把你的接线图和程序放上来,大家才能帮你找出问题,光说现象没人能帮你找出问题出在哪的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-22 16:34:28 | 显示全部楼层
fish6823 发表于 2016-4-22 13:52
看录像两个轮子都转啊!你问问题要把你的接线图和程序放上来,大家才能帮你找出问题,光说现象没人能帮你找 ...

看第二个录像,最后左边轮子是停了的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-22 16:34:53 | 显示全部楼层
本帖最后由 pig881 于 2016-4-22 16:37 编辑

#include <PID_v1.h>


//========== PID 参数 ======================================

double Setpoint=0, Input, Output;
double   Kp=0.2, Ki=0, Kd=0.08;   //  Kp=0.1;   Kp=0.1, Ki=0.05, Kd=0.001;   Kp=0.2, Ki=0, Kd=0.08;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


//========== End of PID 参数 ===================================



//============= 测速参数 ===================
int OUTL=2;
int OUTR=3;

volatile int scode_L = 0; //左轮编码器码盘脉冲计数值
volatile int scode_R =0;  //右轮编码器码盘脉冲计数值

unsigned long old_time=0,new_time=0; // 总时间标记

unsigned long time1 = 0, time2 = 0; //左1,右2 轮 时间标记

double spdLft; //左轮电机每分钟(min)转速(r/min)
double spdRgt; //右轮电机每分钟(min)转速(r/min)

int val_left;//上位机控制字节,用于提供给左轮电机PWM功率值。
int val_right; //小车右轮电机的PWM功率值

int pwm;

//=============END OF 测速参数 ===================




//===================  MOTOR  马达驱动 参数  ===================

// motor A   LEFT MOTOR
int dir1PinAL = 13;
int dir2PinAL = 12;
int speedPinAL = 10; //10脚 LEFT spped setter

// motor B   RIGHT MOTOR
int dir1PinBR = 9;
int dir2PinBR = 8;
int speedPinBR = 6; // 6脚  RIGHT spped setter

//=================== end of MOTOR  马达驱动 参数  ===================



void setMotor()
{
    //左边马达
    pinMode(dir1PinAL,OUTPUT);
    pinMode(dir2PinAL,OUTPUT);
    pinMode(speedPinAL,OUTPUT);

    //右边马达
    pinMode(dir1PinBR,OUTPUT);
    pinMode(dir2PinBR,OUTPUT);
    pinMode(speedPinBR,OUTPUT);   
   
}

//====================== END OF MOTOR 参数 ===============

void Code1();
void Code2();


void setup() {

    setMotor();
    Serial.begin(9600);

     pwm=60;    //=inString.toInt();
     scode_L = 0; //恢复到编码器测速的初始状态
     scode_R = 0;
     old_time=  millis();  

     attachInterrupt(0, Code1, FALLING);//小车左车轮电机的编码器脉冲中断函数
     attachInterrupt(1, Code2, FALLING);//小车右车轮电机的编码器脉冲中断函数

     Setpoint=0;  //左右差为0 为目标
     myPID.SetOutputLimits(-60,60); //输出限制
     
     myPID.SetTunings(Kp,Ki,Kd);
     myPID.SetSampleTime(1000);
     myPID.SetMode(AUTOMATIC);

}

void loop() {

    //======================= 测速代码 ==========================================
   
    new_time=millis();
    if(abs(new_time - old_time) >= 1000) // 如果计时时间已达1秒
    {
      detachInterrupt(0); // 关闭外部中断0
      detachInterrupt(1); // 关闭外部中断1   
      
       //把每一秒钟编码器码盘计得的脉冲数,换算为当前转速值
       //转速单位是每分钟多少转,即r/min。这个编码器码盘为12个齿。
      
          spdLft =(float)scode_L*60/20;//小车左车轮电机转速      
          spdRgt =(float)scode_R*60/20; //小车右车轮电机转速  


          //val_right=(float)val_right+(rpm1-rpm2)*0.4;

          Input=0.6*(spdLft-spdRgt);   这里我用的 0.6 X 左右速度差作为PID输入,我是根据一篇文章提示这么做  的 ,具体应该多少我也不懂
          myPID.Compute();

          val_right=pwm-Output;
          val_left=pwm+Output;
         
         testNum('n');     
   
         scode_L = 0; //恢复到编码器测速的初始状态
         scode_R = 0;
         
         old_time=  millis();   
         
         attachInterrupt(0, Code1,FALLING); // 重新开放外部中断0
         attachInterrupt(1, Code2,FALLING); // 重新开放外部中断1  
        

               

    }
   //======================= END OF 测速代码 ==========================================


    advance();     

}



// 左侧车轮电机的编码器码盘计数中断子程序
void Code1()
{  
  //为了不计入噪音干扰脉冲,
   //当2次中断之间的时间大于5ms时,计一次有效计数
  if((millis()-time1)>5)
  //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
  scode_L += 1; // 编码器码盘计数加一  
  time1=millis();
}




// 右侧车轮电机的编码器码盘计数中断子程序
void Code2()
{  
  if((millis()-time2)>5)
  //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
  scode_R += 1; // 编码器码盘计数加一
  time2=millis();  
}



//子程序程序段
void advance()//小车前进
{
     MOTORDRIVE(speedPinAL,dir1PinAL,dir2PinAL,val_left,0); //左边马达
     MOTORDRIVE(speedPinBR,dir1PinBR,dir2PinBR,val_right,0); //右边马达
}


void back()//小车后退
{
     MOTORDRIVE(speedPinAL,dir1PinAL,dir2PinAL,val_left,1); //左边马达
     MOTORDRIVE(speedPinBR,dir1PinBR,dir2PinBR,val_right,1); //右边马达
}


void Stop()//小车停止
{
     MOTORDRIVE(speedPinAL,dir1PinAL,dir2PinAL,0,1); //左边马达
     MOTORDRIVE(speedPinBR,dir1PinBR,dir2PinBR,0,1); //右边马达
}


//============================= 马达驱动函数 ====================================================

// speedpin:速度引脚  dirPinA:电机极A , dirPinB:电机极B , mspeed:速度值 ,dir:1 正向 0 反向
void MOTORDRIVE(int speedpin,int dirPinA,int dirPinB,int mspeed,int dir)
{
     analogWrite(speedpin,mspeed);   


   if (dir == 1) {  
     digitalWrite(dirPinA,LOW);
     digitalWrite(dirPinB,HIGH);     
   }
   else if(dir== 0) {//反转
      digitalWrite(dirPinA,HIGH);
      digitalWrite(dirPinB,LOW);   
   }
   else {
       analogWrite(speedpin,0);
    }
     
  
}

//============================= end of 马达驱动函数 ====================================================



// ================== 显示函数 =============

void testNum(char a)
{
  if(a=='n')
  {
    Serial.print("Input=");
    Serial.println(Input);

   Serial.print("Output=");
    Serial.println(Output);

         Serial.print("val_left=");
   Serial.println(val_left);

        Serial.print("val_right=");
   Serial.println(val_right);

    Serial.print("\t speeds left=");
   Serial.println(spdLft);

     Serial.print("\t speeds Right=");
   Serial.println(spdRgt);
  }
  else if (a=='t')
  {


   
   
    Serial.print(spdLft);
   Serial.print(",");
   
    Serial.println(spdRgt);
    Serial.print("\n");
  }

        

    delay(1000);
}


回复 支持 反对

使用道具 举报

发表于 2016-4-22 20:06:48 | 显示全部楼层
插着USB线正常,拔掉出问题,估摸着硬件BUG的可能比较大
回复 支持 反对

使用道具 举报

发表于 2019-3-25 20:19:24 | 显示全部楼层
请问你是同时用编码器的AB相的吗
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-6 20:35 , Processed in 0.149400 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表