极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 22393|回复: 12

pwm 无法调节电机速度

[复制链接]
发表于 2014-4-13 17:44:09 | 显示全部楼层 |阅读模式
我用电机控制板LN298 驱动电机,接线不用说了,很简单。程序如下:

  1. //=================motor=======================
  2. //Motor A
  3. int PWMA = 9; //Speed control
  4. int Left_1 = 8; //Direction
  5. int Left_2 = 7; //Direction

  6. //Motor B
  7. int PWMB = 10; //Speed control
  8. int Right_1 = 6; //Direction
  9. int Right_2 = 5; //Direction

  10. int PWMA_Start=30;
  11. int PWMB_Start=30;
  12. //=========================================================

  13. 。。。中间省略

  14. void motor_move(int dir,int PWMA_VAL,int PWMB_VAL)//当 dir=1,表示前进,当 dir=2表示 后退 //
  15. {
  16.    switch(dir){
  17.      case 1://当 dir=1,表示前进//
  18.         digitalWrite (Left_1,HIGH);
  19.         digitalWrite(Left_2,LOW);
  20.         analogWrite(PWMA,PWMA_VAL);
  21.         digitalWrite (Right_1,HIGH);
  22.         digitalWrite(Right_2,LOW);
  23.         analogWrite(PWMB,PWMB_VAL);
  24.         break;
  25.      case 2://backward
  26.         digitalWrite (Left_1,LOW);
  27.         digitalWrite(Left_2,HIGH);
  28.         analogWrite(PWMA,PWMA_VAL);
  29.         digitalWrite (Right_1,LOW);
  30.         digitalWrite(Right_2,HIGH);
  31.         analogWrite(PWMB,PWMB_VAL);
  32.         break;
  33.      case 3://turn left
  34.         digitalWrite (Left_1,HIGH);
  35.         digitalWrite(Left_2,LOW);
  36.         analogWrite(PWMA,PWMA_VAL);
  37.         digitalWrite (Right_1,LOW);
  38.         digitalWrite(Right_2,HIGH);
  39.         analogWrite(PWMB,PWMB_VAL);
  40.         break;
  41.       case 4://turn right
  42.         digitalWrite (Left_1,LOW);
  43.         digitalWrite(Left_2,HIGH);
  44.         analogWrite(PWMA,PWMA_VAL);
  45.         digitalWrite (Right_1,HIGH);
  46.         digitalWrite(Right_2,LOW);
  47.         analogWrite(PWMB,PWMB_VAL);
  48.         break;
  49.       case 5://stop
  50.         digitalWrite (Left_1,HIGH);
  51.         digitalWrite(Left_2,HIGH);
  52.         analogWrite(PWMA,PWMA_VAL);
  53.         digitalWrite (Right_1,HIGH);
  54.         digitalWrite(Right_2,HIGH);
  55.         analogWrite(PWMB,PWMB_VAL);
  56.         break;
  57.     }
  58. }
复制代码


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

使用道具 举报

 楼主| 发表于 2014-4-13 17:49:21 | 显示全部楼层
  1. #include <I2Cdev.h>
  2. #include <MPU6050.h>
  3. #include <Wire.h>
  4. #include <stdlib.h>
  5. //=================motor=======================
  6. //Motor A
  7. int PWMA = 9; //Speed control
  8. int Left_1 = 8; //Direction
  9. int Left_2 = 7; //Direction

  10. //Motor B
  11. int PWMB = 10; //Speed control
  12. int Right_1 = 6; //Direction
  13. int Right_2 = 5; //Direction

  14. int PWMA_Start=30;
  15. int PWMB_Start=30;
  16. //=========================================================
  17. MPU6050 accelgyro;
  18. unsigned long now, lastTime = 0;

  19. float dt;                                   //微分时间

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

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

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

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

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

  34. void setup(){

  35.   Wire.begin();
  36.   Serial.begin(38400);
  37.   //====================motor_setting===================
  38.   pinMode(PWMA, OUTPUT);
  39.   pinMode(Left_1, OUTPUT);
  40.   pinMode(Left_2, OUTPUT);

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

  55. void loop(){

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

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

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

  83.   /* kalmen start */
  84.   Sx = 0; Rx = 0;
  85.   Sy = 0; Ry = 0;
  86.   for(int i=1;i<10;i++){               //测量值平均值运算
  87.     a_x[i-1] = a_x[i];                 //即加速度平均值
  88.     Sx += a_x[i];
  89.     a_y[i-1] = a_y[i];
  90.     Sy += a_y[i];
  91.   }
  92.   a_x[9] = aax;
  93.   Sx += aax;
  94.   Sx /= 10;                                 //x轴加速度平均值
  95.   a_y[9] = aay;
  96.   Sy += aay;
  97.   Sy /= 10;                                 //y轴加速度平均值

  98.   for(int i=0;i<10;i++){
  99.     Rx += sq(a_x[i] - Sx);
  100.     Ry += sq(a_y[i] - Sy);
  101.   }
  102.   Rx = Rx / 9;                              //得到方差
  103.   Ry = Ry / 9;                        
  104.   Px = Px + 0.0025;                    // 0.0025在下面有说明...
  105.   Kx = Px / (Px + Rx);                 //计算卡尔曼增益
  106.   agx = agx + Kx * (aax - agx);       //陀螺仪角度与加速度计速度叠加
  107.   Px = (1 - Kx) * Px;                    //更新p值
  108.   Py = Py + 0.0025;
  109.   Ky = Py / (Py + Ry);
  110.   agy = agy + Ky * (aay - agy);
  111.   Py = (1 - Ky) * Py;
  112.   /* kalmen end */
  113.   Serial.print(agx);Serial.print(",");
  114.   Serial.print(agy);Serial.println();
  115.   
  116.    if(-3<agy){
  117.       motor_move(1,PWMA_Start,PWMA_Start);
  118.    }
  119.    else if(-4.0>agy){
  120.       motor_move(2,PWMA_Start,PWMB_Start);
  121.    }
  122.    else
  123.    {
  124.       motor_move(5,0,0);
  125.    }

  126. }

  127. //============================motor function========================
  128. void motor_move(int dir,int PWMA_VAL,int PWMB_VAL)//当 dir=1,表示前进,当 dir=2表示 后退 //
  129. {
  130.    switch(dir){
  131.      case 1://当 dir=1,表示前进//
  132.         digitalWrite (Left_1,HIGH);
  133.         digitalWrite(Left_2,LOW);
  134.         analogWrite(PWMA,PWMA_VAL);
  135.         digitalWrite (Right_1,HIGH);
  136.         digitalWrite(Right_2,LOW);
  137.         analogWrite(PWMB,PWMB_VAL);
  138.         break;
  139.      case 2://backward
  140.         digitalWrite (Left_1,LOW);
  141.         digitalWrite(Left_2,HIGH);
  142.         analogWrite(PWMA,PWMA_VAL);
  143.         digitalWrite (Right_1,LOW);
  144.         digitalWrite(Right_2,HIGH);
  145.         analogWrite(PWMB,PWMB_VAL);
  146.         break;
  147.      case 3://turn left
  148.         digitalWrite (Left_1,HIGH);
  149.         digitalWrite(Left_2,LOW);
  150.         analogWrite(PWMA,PWMA_VAL);
  151.         digitalWrite (Right_1,LOW);
  152.         digitalWrite(Right_2,HIGH);
  153.         analogWrite(PWMB,PWMB_VAL);
  154.         break;
  155.       case 4://turn right
  156.         digitalWrite (Left_1,LOW);
  157.         digitalWrite(Left_2,HIGH);
  158.         analogWrite(PWMA,PWMA_VAL);
  159.         digitalWrite (Right_1,HIGH);
  160.         digitalWrite(Right_2,LOW);
  161.         analogWrite(PWMB,PWMB_VAL);
  162.         break;
  163.       case 5://stop
  164.         digitalWrite (Left_1,HIGH);
  165.         digitalWrite(Left_2,HIGH);
  166.         analogWrite(PWMA,PWMA_VAL);
  167.         digitalWrite (Right_1,HIGH);
  168.         digitalWrite(Right_2,HIGH);
  169.         analogWrite(PWMB,PWMB_VAL);
  170.         break;
  171.     }
  172. }
  173. //==================================================================
复制代码
程序参考了别人的,具体名字忘了,在此谢过。
这个只是用了其中一个轴,实际上有些代码可以省略,没有去改,只是用角度控制,但是没有用到PID计算设定电机速度,车子站立后抖动厉害,速度无法调节是很大原因,过调严重。速度是按最大值输出的,不知道什么原因导致PWM调节失效。
回复 支持 反对

使用道具 举报

发表于 2014-4-13 20:47:48 | 显示全部楼层
應檢查以下的 dir ,PWMA 及 PWMB 的傳來值是否正確。

void motor_move(int dir,int PWMA_VAL,int PWMB_VAL)//当 dir=1,表示前进,当 dir=2表示 后退 //
...
回复 支持 反对

使用道具 举报

发表于 2014-4-13 21:01:20 | 显示全部楼层
L298N 使能(ENA ENB)端要接高电平。其他两脚接控制端,一端接pwm 。一端接普通数字口控制正反向
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-4-14 09:33:44 | 显示全部楼层
eddiewwm 发表于 2014-4-13 20:47
應檢查以下的 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
L298N 使能(ENA ENB)端要接高电平。其他两脚接控制端,一端接pwm 。一端接普通数字口控制正反向

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-4-14 10:02:53 | 显示全部楼层
究竟是什么问题呢?
回复 支持 反对

使用道具 举报

发表于 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
//Motor A
int PWMA = 9; //pwm控制是吧
int Left_1 = 8; //

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

PWMB才是控制电机Right使能端
回复 支持 反对

使用道具 举报

发表于 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
能上张你的接线图吗?看你的图没看出PWMA与B接哪里,而且PWM值30太低了,一般电机不会动的,一般是100左右才 ...

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

使用道具 举报

发表于 2014-4-14 18:13:19 | 显示全部楼层
活着就是幸福 发表于 2014-4-14 16:01
这个图是说明书的,不可能错的呀,兄弟,PWM值我不管设多少都一样,这才是问题。

我的意思是你的9、10口接的是图中ENA、ENB那两个跳线的口?
回复 支持 反对

使用道具 举报

发表于 2014-4-15 20:45:26 | 显示全部楼层
活着就是幸福 发表于 2014-4-14 09:33
输入的值是没有问题的,谢谢你的回答。

若真已確認輸入值沒問題,而函數也是已知可行的,那麼剩下來的就是硬件和接線等問題了!
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 02:06 , Processed in 0.042423 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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