极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18946|回复: 1

arduino 中断和PWM输出冲突

[复制链接]
发表于 2014-5-29 09:46:55 | 显示全部楼层 |阅读模式
自己在试着做两轮车,编码器这里遇到了点问题,小车在往一个方向转的时候总是顿顿的,另外一边就没事,去掉码盘就好了。刚才看到论坛上说中断与pwm冲突,所以求教一下程序应该怎么改呀。
  1. #include <Wire.h>
  2. #include <ADXL345.h>
  3. #include <L3G4200DJ.h>

  4. ADXL345 acceleration;
  5. L3G4200DJ gyro;
  6. #define Gry_offset -20     // 陀螺仪偏移量
  7. #define Gyr_Gain -0.07      // 满量程2000dps时灵敏度(dps/digital)
  8. #define pi 3.14159
  9. #define drift 50

  10. double Setpoint, Input, Output;
  11. double Klm_angle;
  12. double kp = 5.3;
  13. unsigned long preTime = 0; // 采样时间
  14. double f_angle = 0.0;       // 滤波处理后的角度值
  15. int x;

  16. #define Q_angle 0.01      // 角度数据置信度
  17. #define Q_omega 0.0003    // 角速度数据置信度
  18. #define R_angle 0.03      // 方差噪声
  19. double bias = 0;
  20. double P_00 = 0, P_01 = 0, P_10 = 0, P_11 = 0;

  21. unsigned long lastTime;           // 前次时间
  22. double ITerm, lastInput;    // 积分项、前次输入
  23. unsigned long time = 0, old_time = 0; // 时间标记
  24. unsigned long time1 = 0, time2 = 0; // 时间标记
  25. double count1 = 0;  //左轮编码器码盘脉冲计数值
  26. double count2= 0; //右轮编码器码盘脉冲计数值
  27. double rpm1 = 0;  //左轮电机每分钟(min)转速(r/min)
  28. double rpm2 = 0;  //右轮电机每分钟(min)转速(r/min)
  29. double  Output1,Output2,Output_x;

  30. void setup() {
  31.    pinMode(10,OUTPUT);//1号电机转向
  32.    pinMode(11,OUTPUT);//1号电机转速
  33.    pinMode(5,OUTPUT);//2号电机转向
  34.    pinMode(6,OUTPUT);//2号电机转速
  35.       pinMode(2,INPUT); //伺服电机编码器的OUTA和OUTB信号端设置为输入模式
  36.   pinMode(8,INPUT);
  37.   pinMode(3,INPUT);
  38.   pinMode(9,INPUT);
  39.   Serial.begin(9600);
  40.   Wire.begin();
  41.   acceleration.Init_ADXL345();
  42.   gyro.Init_L3G4200DJ();
  43.     Setpoint=0.00;
  44.     attachInterrupt(0, Code1, FALLING);//小车左车轮电机的编码器脉冲中断函数
  45.   attachInterrupt(1, Code2, FALLING);//小车右车轮电机的编码器脉冲中断函数
  46. }

  47. void loop() {
  48.       unsigned long now = millis();                           // 当前时间(ms)
  49.     double dt = (now - preTime) / 1000.0;                    // 微分时间(s)
  50.     preTime = now;
  51.    
  52.   acceleration.Out_ADXL345();
  53.   gyro.Out_L3G4200DJ();
  54.   
  55.   double a_a=acceleration.a.x;
  56.   double a_c=acceleration.a.z;
  57.   double g_b=gyro.g.y;
  58.   double angleA = atan(a_a / a_c) * 180 / pi;          // 根据加速度分量得到的角度(degree)
  59.   double omega =  Gyr_Gain * (g_b +  Gry_offset); // 当前角速度(degree/s)

  60.     Klm_angle += (omega - bias) * dt;          // 先验估计
  61.     P_00 += -(P_10 + P_01) * dt + Q_angle *dt;
  62.     P_01 += -P_11 * dt;
  63.     P_10 += -P_11 * dt;
  64.     P_11 += +Q_omega * dt;                     // 先验估计误差协方差
  65.    
  66.     double K_0 = P_00 / (P_00 + R_angle);
  67.     double K_1 = P_10 / (P_00 + R_angle);
  68.    
  69.     bias += K_1 * (angleA - Klm_angle);
  70.     Klm_angle += K_0 * (angleA - Klm_angle);   // 后验估计
  71.     P_00 -= K_0 * P_00;
  72.     P_01 -= K_0 * P_01;
  73.     P_10 -= K_1 * P_00;
  74.     P_11 -= K_1 * P_01;
  75.    
  76.           if(Klm_angle>1.36){
  77.         if(36>Klm_angle>1.36)
  78.     { Output=kp*(Klm_angle-1.36);
  79.        Output1=Output;
  80.             Output2=Output+Output_x;
  81.             analogWrite(10,Output1);       //PWM out put
  82.             analogWrite(5,Output2);       //PWM out put
  83.             analogWrite(11,0);       //PWM out put
  84.             analogWrite(6,0);   //PWM out put
  85.     }
  86.     else{
  87.       Output=10*(Klm_angle-1.36);
  88.        Output1=Output;
  89.             Output2=Output+Output_x;
  90.             analogWrite(10,min(Output1,255));       //PWM out put
  91.             analogWrite(5,min(Output2,255));       //PWM out put
  92.             analogWrite(11,0);       //PWM out put
  93.             analogWrite(6,0);   //PWM out put
  94.     }
  95.       }
  96.     if(Klm_angle<1.36)
  97.     {if(-38<Klm_angle<1.36)
  98.     { Output=kp*(Klm_angle-1.36);
  99.           Output = -Output;
  100.      Output1=Output;
  101.             Output2=Output+Output_x;
  102.       analogWrite(11,Output1);       //PWM out put
  103.             analogWrite(6,Output2);       //PWM out put
  104.             analogWrite(10,0);       //PWM out put
  105.             analogWrite(5,0);
  106.     }
  107.     else{
  108.       Output=10*(Klm_angle-1.36);
  109.           Output = -Output;
  110.      Output1=Output;
  111.             Output2=Output+Output_x;
  112.       analogWrite(11,min(Output1,255));       //PWM out put
  113.             analogWrite(6,min(Output2,255));       //PWM out put
  114.             analogWrite(10,0);       //PWM out put
  115.             analogWrite(5,0);
  116.     }
  117.     }

  118.         time = millis();
  119.   if(abs(time - old_time) >= 10) // 如果计时时间已达1秒
  120.   {
  121.     detachInterrupt(0); // 关闭外部中断0
  122.     detachInterrupt(1); // 关闭外部中断1   
  123.      //把每一秒钟编码器码盘计得的脉冲数,换算为当前转速值
  124.      //转速单位是每分钟多少转,即r/min。这个编码器码盘为12个齿。
  125.     rpm1 =(float)count1*60/334;//小车左车轮电机转速
  126.     rpm2 =(float)count2*60/334; //小车右车轮电机转速
  127.     Output_x=(rpm1-rpm2)*(Output/255);
  128.     count1 = 0;   //把脉冲计数值清零,以便计算下一秒的脉冲计数
  129.     count2 = 0;
  130.     old_time=  millis();     // 记录每秒测速时的时间节点   
  131.     attachInterrupt(0, Code1,FALLING); // 重新开放外部中断0
  132.     attachInterrupt(1, Code2,FALLING); // 重新开放外部中断1
  133.   }
  134.         Serial.print(Klm_angle);         
  135.     Serial.print(",  ");
  136.     Serial.print(rpm2);
  137.     Serial.print(",  ");
  138.     Serial.println(Output1);
  139.       delay(10);
  140.     }
  141.     void Code1()
  142. {  
  143.   //为了不计入噪音干扰脉冲,
  144.    //当2次中断之间的时间大于5ms时,计一次有效计数
  145.   if((millis()-time1)>5)
  146.   //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
  147.   count1 += 1; // 编码器码盘计数加一  
  148.   time1==millis();
  149. }
  150. // 右侧车轮电机的编码器码盘计数中断子程序
  151. void Code2()
  152. {  
  153.   if((millis()-time2)>5)
  154.   //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
  155.   count2 += 1; // 编码器码盘计数加一
  156.   time2==millis();  
  157. }
复制代码
回复

使用道具 举报

发表于 2015-5-14 17:21:24 | 显示全部楼层
请问楼主怎么解决的呢??
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-24 08:36 , Processed in 0.038407 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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