活着就是幸福 发表于 2014-4-13 17:44:09

pwm 无法调节电机速度

我用电机控制板LN298 驱动电机,接线不用说了,很简单。程序如下:

//=================motor=======================
//Motor A
int PWMA = 9; //Speed control
int Left_1 = 8; //Direction
int Left_2 = 7; //Direction

//Motor B
int PWMB = 10; //Speed control
int Right_1 = 6; //Direction
int Right_2 = 5; //Direction

int PWMA_Start=30;
int PWMB_Start=30;
//=========================================================

。。。中间省略

void motor_move(int dir,int PWMA_VAL,int PWMB_VAL)//当 dir=1,表示前进,当 dir=2表示 后退 //
{
   switch(dir){
   case 1://当 dir=1,表示前进//
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,LOW);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,HIGH);
      digitalWrite(Right_2,LOW);
      analogWrite(PWMB,PWMB_VAL);
      break;
   case 2://backward
      digitalWrite (Left_1,LOW);
      digitalWrite(Left_2,HIGH);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,LOW);
      digitalWrite(Right_2,HIGH);
      analogWrite(PWMB,PWMB_VAL);
      break;
   case 3://turn left
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,LOW);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,LOW);
      digitalWrite(Right_2,HIGH);
      analogWrite(PWMB,PWMB_VAL);
      break;
      case 4://turn right
      digitalWrite (Left_1,LOW);
      digitalWrite(Left_2,HIGH);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,HIGH);
      digitalWrite(Right_2,LOW);
      analogWrite(PWMB,PWMB_VAL);
      break;
      case 5://stop
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,HIGH);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,HIGH);
      digitalWrite(Right_2,HIGH);
      analogWrite(PWMB,PWMB_VAL);
      break;
    }
}

但是改变PWM值无法调节速度,不知道什么原因,有人遇到过吗?有解决办法吗?帮忙看看是不是程序的问题。

活着就是幸福 发表于 2014-4-13 17:49:21

#include <I2Cdev.h>
#include <MPU6050.h>
#include <Wire.h>
#include <stdlib.h>
//=================motor=======================
//Motor A
int PWMA = 9; //Speed control
int Left_1 = 8; //Direction
int Left_2 = 7; //Direction

//Motor B
int PWMB = 10; //Speed control
int Right_1 = 6; //Direction
int Right_2 = 5; //Direction

int PWMA_Start=30;
int PWMB_Start=30;
//=========================================================
MPU6050 accelgyro;
unsigned long now, lastTime = 0;

float dt;                                 //微分时间

int16_t ax, ay, az, gx, gy, gz;             //加速度计陀螺仪原始数据
float aax=0, aay=0, agx=0, agy=0, agz=0;    //角度变量
long axo = 0, ayo = 0, azo = 0;             //加速度计偏移量
long gxo = 0, gyo = 0, gzo = 0;             //陀螺仪偏移量

float pi = 3.1415926;
float AcceRatio = 16384.0;            //加速度计比例系数
float GyroRatio = 131.0;               //陀螺仪比例系数

uint8_t n_sample = 8;                  //加速度计滤波算法采样个数
float aaxs = {0}, aays = {0};    //x,y轴采样队列
long aax_sum, aay_sum;               //x,y轴采样和

float a_x={0},a_y={0},g_x={0},g_y={0};//加速度计协方差计算队列
float Px=1, Rx, Kx, Sx, Vx, Qx;       //x轴卡尔曼变量
float Py=1, Ry, Ky, Sy, Vy, Qy;       //y轴卡尔曼变量

////=================加入串口通信代码调试==========================

void setup(){

Wire.begin();
Serial.begin(38400);
//====================motor_setting===================
pinMode(PWMA, OUTPUT);
pinMode(Left_1, OUTPUT);
pinMode(Left_2, OUTPUT);

pinMode(PWMB, OUTPUT);
pinMode(Right_1, OUTPUT);
pinMode(Right_2, OUTPUT);
//======================================================
accelgyro.initialize();             //初始化
unsigned short times = 100;         //采样次数
for(int i=0;i<times;i++){
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //读取六轴原始数值
    axo += ax; ayo += ay; azo += az;                  //采样和
    gxo += gx; gyo += gy; gzo += gz;
}
axo /= times; ayo /= times; azo /= times; //计算加速度计偏移
gxo /= times; gyo /= times; gzo /= times; //计算陀螺仪偏移
}

void loop(){

unsigned long now = millis();      //当前时间(ms)
dt = (now - lastTime) / 1000.0;      //微分时间(s)
lastTime = now;                      //上一次采样时间(ms)
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);//读取六轴原始数值

float accx = ax / AcceRatio;         //x轴加速度
float accy = ay / AcceRatio;         //y轴加速度
float accz = az / AcceRatio;         //z轴加速度

aax = atan(accy / accz) * (-180) / pi;//x轴对于水平面的夹角
aay = atan(accx / accz) * 180 / pi;   //y轴对于水平面的夹角
aax_sum = 0;                            // 对于加速度计原始数据的滑动加权滤波算法
aay_sum = 0;
for(int i=1;i<n_sample;i++){
    aaxs = aaxs;
    aax_sum += aaxs * i;
    aays = aays;
    aay_sum += aays * i;
}
aaxs = aax;
aax_sum += aax * n_sample;
aax = (aax_sum / (11*n_sample/2.0)) * 9 / 7.0;         //角度调幅至0-90°
aays = aay;                              //此处应用实验法取得合适的系数
aay_sum += aay * n_sample;                           //本例系数为9/7
aay = (aay_sum / (11*n_sample/2.0)) * 9 / 7.0;
float gyrox = - (gx-gxo) / GyroRatio * dt;             //x轴角速度
float gyroy = - (gy-gyo) / GyroRatio * dt;             //y轴角速度
agx += gyrox;                                          //x轴角速度积分
agy += gyroy;                                          //x轴角速度积分

/* kalmen start */
Sx = 0; Rx = 0;
Sy = 0; Ry = 0;
for(int i=1;i<10;i++){               //测量值平均值运算
    a_x = a_x;               //即加速度平均值
    Sx += a_x;
    a_y = a_y;
    Sy += a_y;
}
a_x = aax;
Sx += aax;
Sx /= 10;                                 //x轴加速度平均值
a_y = aay;
Sy += aay;
Sy /= 10;                                 //y轴加速度平均值

for(int i=0;i<10;i++){
    Rx += sq(a_x - Sx);
    Ry += sq(a_y - Sy);
}
Rx = Rx / 9;                              //得到方差
Ry = Ry / 9;                        
Px = Px + 0.0025;                  // 0.0025在下面有说明...
Kx = Px / (Px + Rx);               //计算卡尔曼增益
agx = agx + Kx * (aax - agx);       //陀螺仪角度与加速度计速度叠加
Px = (1 - Kx) * Px;                  //更新p值
Py = Py + 0.0025;
Ky = Py / (Py + Ry);
agy = agy + Ky * (aay - agy);
Py = (1 - Ky) * Py;
/* kalmen end */
Serial.print(agx);Serial.print(",");
Serial.print(agy);Serial.println();

   if(-3<agy){
      motor_move(1,PWMA_Start,PWMA_Start);
   }
   else if(-4.0>agy){
      motor_move(2,PWMA_Start,PWMB_Start);
   }
   else
   {
      motor_move(5,0,0);
   }

}

//============================motor function========================
void motor_move(int dir,int PWMA_VAL,int PWMB_VAL)//当 dir=1,表示前进,当 dir=2表示 后退 //
{
   switch(dir){
   case 1://当 dir=1,表示前进//
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,LOW);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,HIGH);
      digitalWrite(Right_2,LOW);
      analogWrite(PWMB,PWMB_VAL);
      break;
   case 2://backward
      digitalWrite (Left_1,LOW);
      digitalWrite(Left_2,HIGH);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,LOW);
      digitalWrite(Right_2,HIGH);
      analogWrite(PWMB,PWMB_VAL);
      break;
   case 3://turn left
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,LOW);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,LOW);
      digitalWrite(Right_2,HIGH);
      analogWrite(PWMB,PWMB_VAL);
      break;
      case 4://turn right
      digitalWrite (Left_1,LOW);
      digitalWrite(Left_2,HIGH);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,HIGH);
      digitalWrite(Right_2,LOW);
      analogWrite(PWMB,PWMB_VAL);
      break;
      case 5://stop
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,HIGH);
      analogWrite(PWMA,PWMA_VAL);
      digitalWrite (Right_1,HIGH);
      digitalWrite(Right_2,HIGH);
      analogWrite(PWMB,PWMB_VAL);
      break;
    }
}
//==================================================================程序参考了别人的,具体名字忘了,在此谢过。
这个只是用了其中一个轴,实际上有些代码可以省略,没有去改,只是用角度控制,但是没有用到PID计算设定电机速度,车子站立后抖动厉害,速度无法调节是很大原因,过调严重。速度是按最大值输出的,不知道什么原因导致PWM调节失效。

eddiewwm 发表于 2014-4-13 20:47:48

應檢查以下的 dir ,PWMA 及 PWMB 的傳來值是否正確。

void motor_move(int dir,int PWMA_VAL,int PWMB_VAL)//当 dir=1,表示前进,当 dir=2表示 后退 //
...

Workspace 发表于 2014-4-13 21:01:20

L298N 使能(ENA ENB)端要接高电平。其他两脚接控制端,一端接pwm 。一端接普通数字口控制正反向

活着就是幸福 发表于 2014-4-14 09:33:44

eddiewwm 发表于 2014-4-13 20:47 static/image/common/back.gif
應檢查以下的 dir ,PWMA 及 PWMB 的傳來值是否正確。

void motor_move(int dir,int PWMA_VAL,int PWMB_ ...

输入的值是没有问题的,谢谢你的回答。

活着就是幸福 发表于 2014-4-14 10:01:59

Workspace 发表于 2014-4-13 21:01 static/image/common/back.gif
L298N 使能(ENA ENB)端要接高电平。其他两脚接控制端,一端接pwm 。一端接普通数字口控制正反向

使能端高电平是默认设置,没有改动,完全是按照这个说明图接的,应该没有问题呀。

活着就是幸福 发表于 2014-4-14 10:02:53

究竟是什么问题呢?

Workspace 发表于 2014-4-14 11:27:07

//Motor A
int PWMA = 9; //pwm控制是吧
int Left_1 = 8; //
int Left_2 = 7; //
7是使能端或者8是
但是
case 1://当 dir=1,表示前进//
      digitalWrite (Left_1,HIGH);
      digitalWrite(Left_2,LOW);

case 2://backward
      digitalWrite (Left_1,LOW);
      digitalWrite(Left_2,HIGH);//使能端一会高一会低。肯定不行
//还有要是改变电机速度必须改变PWM的值(0-255)

活着就是幸福 发表于 2014-4-14 13:17:26

Workspace 发表于 2014-4-14 11:27 static/image/common/back.gif
//Motor A
int PWMA = 9; //pwm控制是吧
int Left_1 = 8; //


8,7是数字端控制电机left方向的

PWMB才是控制电机Right使能端

fish6823 发表于 2014-4-14 14:56:33

本帖最后由 fish6823 于 2014-4-14 14:59 编辑

能上张你的接线图吗?看你的图没看出PWMA与B接哪里,而且PWM值30太低了,一般电机不会动的,一般是100左右才动,你的电机能动是不是接错线了。
按说应该是A1、A2、B1、B2接正反转控制,ENA、ENB接PWM,但你的图上ENA、ENB短接了。

活着就是幸福 发表于 2014-4-14 16:01:15

fish6823 发表于 2014-4-14 14:56 static/image/common/back.gif
能上张你的接线图吗?看你的图没看出PWMA与B接哪里,而且PWM值30太低了,一般电机不会动的,一般是100左右才 ...

这个图是说明书的,不可能错的呀,兄弟,PWM值我不管设多少都一样,这才是问题。

fish6823 发表于 2014-4-14 18:13:19

活着就是幸福 发表于 2014-4-14 16:01 static/image/common/back.gif
这个图是说明书的,不可能错的呀,兄弟,PWM值我不管设多少都一样,这才是问题。

我的意思是你的9、10口接的是图中ENA、ENB那两个跳线的口?

eddiewwm 发表于 2014-4-15 20:45:26

活着就是幸福 发表于 2014-4-14 09:33 static/image/common/back.gif
输入的值是没有问题的,谢谢你的回答。

若真已確認輸入值沒問題,而函數也是已知可行的,那麼剩下來的就是硬件和接線等問題了!
页: [1]
查看完整版本: pwm 无法调节电机速度