背景:arduino uno r3,mpu6050用i2c,l298n驱动,蓝牙从,直流减速电机,电源18650两节实际电压8v左右一路供arduino一路升压供驱动
出现问题:调试过程中会出现电机突然停在某个转速上不再更新,期间角度输出不再更新;经过一段时间的折腾烧芯片之类的现在问题变严重,电机一转就读不了mpu6050数据。情况类似 http://www.geek-workshop.com/thread-1548-1-1.html
自己折腾期间成果如下:
确定在软件中的具体停止运行的语句位置:
循环中主控芯片读取当前倾角传感器模块获得的姿态信息
确定出错条件:
未给电机驱动供电时,正常读取
电机供电但PWM值给定较小,电机未能正常转动时,正常读取
电机供电且给定PWM值较大,电机正常转动后,
较低转速下可以正常读取几秒,高转速下无法读取
目前已排除如下原因:
由于驱动与主控模块使用同一电源产生的电压干扰
MPU6050运行时受电机电磁干扰
Arduino主控模块电路存在问题导致的IIC总线受阻
有没有大神有遇到这个问题恳切地希望指导一二~
程序如下: - ////////////基于Arduino的两轮自平衡机器人 ////////////
- #include "Wire.h" //Wire库
- #include "I2Cdev.h" //IIC总线
- #include "MPU6050.h" //加速度计和陀螺仪传感器
- int Encoder_left =2; //中断0,用于左轮转速测量
- int C_left =4;
- int Encoder_right= 3; //中断1,用于右轮转速测量
- int C_right =5;
- int E_left =10; //左轮控制及输出
- int M_left =8;
- int M_left2 =9;
- int E_right =11; //右轮控制及输出
- int M_right =12;
- int M_right2 =13;
- int PWM_left =0; //左轮PWM输出值
- int PWM_right =0; //右轮PWM输出值
- int count_left =0; //左轮转速
- int count_right =0; //右轮转速
- MPU6050 accelgyro;
- int16_t ax, ay, az, gx, gy, gz;
- float Angle_ax; //由加速度计算的倾斜角度
- float Gyro_gy; //由Y轴陀螺仪计算得到的角速度
- float Angle; //小车倾斜角度
- float Setpoint =-2; //小车直立平衡倾角
- char val = 'Z'; //蓝牙遥控信号暂存
- int Speed_need =0;
- int Turn_need =0;
- float speeds,speeds_filter, positions;
- float diff_speeds,diff_speeds_all;
- float K =0.95;//一阶互补滤波系数
- float dt =0.005;
- float Kp =25, Kd =0.5, Ksp =0, Ksi =Ksp/200;
- int Output =0;
- void Code_left() { //左轮编码器计数中断程序
- if (digitalRead(Encoder_left) == LOW) {
- if (digitalRead(C_left) == LOW) count_left--;
- else count_left++;
- }
- else {
- if (digitalRead(C_left) == LOW) count_left++;
- else count_left--;
- }
- }
- void Code_right() { //右轮编码器计数中断程序
- if (digitalRead(Encoder_right) == LOW) {
- if (digitalRead(C_right) == LOW) count_right++;
- else count_right--;
- }
- else {
- if (digitalRead(C_right) == LOW) count_right--;
- else count_right++;
- }
- }
- void setup() {
- Wire.begin();
- Serial.begin(115200);
- accelgyro.initialize(); //MPU6050初始化
- delay(100);
-
- pinMode(E_left, OUTPUT); pinMode(M_left, OUTPUT); pinMode(M_left2, OUTPUT); //左轮控制引脚
- pinMode(E_right, OUTPUT); pinMode(M_right, OUTPUT); pinMode(M_right2, OUTPUT); //右轮控制引脚
- pinMode(6, OUTPUT); digitalWrite(6,HIGH); //电机编码器正极
- pinMode(7, OUTPUT); digitalWrite(7,HIGH);
- pinMode(Encoder_left, INPUT); pinMode(C_left, INPUT); //编码器信号读取
- pinMode(Encoder_right, INPUT); pinMode(C_right, INPUT);
-
- attachInterrupt(0, Code_left, CHANGE); attachInterrupt(1, Code_right, CHANGE); //利用跳变沿进入中断程序测速
- }
- void SetMotorVoltage(int LeftVol, int RightVol) { //电机控制
- if(LeftVol >= 0)
- {digitalWrite(M_left,HIGH);
- digitalWrite(M_left2,LOW);}
- else
- {digitalWrite(M_left,LOW);
- digitalWrite(M_left2,HIGH);
- LeftVol = -LeftVol;}
- if(RightVol >= 0)
- {digitalWrite(M_right,HIGH);
- digitalWrite(M_right2,LOW);}
- else
- {digitalWrite(M_right,LOW);
- digitalWrite(M_right2,HIGH);
- RightVol = -RightVol;}
-
- if(LeftVol > 255) {LeftVol = 250;} //防止PWM值超过255
- if(RightVol > 255) {RightVol = 250;} //防止PWM值超过255
-
- analogWrite(E_left,LeftVol);
- analogWrite(E_right,RightVol);
- }
- void Angle_Calcu(void) { //计算当前倾角
- Angle_ax = (ax-955)/263; //去除零点偏移955,//±2g //16384*0.92*3.14/180 //弧度转换为度
- Gyro_gy = -(gy-239)/131; //去除零点偏移239,//±250°/s //131 //负号为方向处理
- Angle = K*(Angle+Gyro_gy*dt)+(1-K)*Angle_ax; //一阶互补滤波
- Serial.print(millis());Serial.print("\t");Serial.println(Angle);
- }
- void PWM_Calcu(void) { //计算输出PWM值
- if (abs(Angle-Setpoint) > 30) { //角度大于30度时停止PWM输出速度积分清零
- SetMotorVoltage(0,0);
- positions = 0;
- }
- else {
- diff_speeds = (count_left - count_right)*0.5; //求得两轮速度差用于直行时的转向调整
- diff_speeds_all += diff_speeds;
- speeds = (count_left + count_right)*0.5;
- speeds_filter = 0.8*speeds_filter+0.2*speeds; //一阶互补滤波
- positions += speeds_filter;
- positions -= Speed_need;
- positions = constrain(positions, -200, 200); //抗积分饱和
- count_left = 0; //编码器测得速度清零
- count_right = 0;
- Output = Kp*(Angle-Setpoint)+Kd*Gyro_gy - (Ksp*speeds_filter+Ksi*positions); //角度环负反馈和速度环正反馈输出叠加
- Serial.println(Output);
- if(Turn_need == 0) { //转向环负反馈输出叠加及转向控制
- PWM_left = Output+diff_speeds_all;
- PWM_right = Output-diff_speeds_all;
- }
- else {
- PWM_left = Output+Turn_need;
- PWM_right = Output-Turn_need;
- }
- SetMotorVoltage(PWM_left,PWM_right);
- }
- }
- void loop() {
- if (Serial.available() > 0) //读蓝牙指令
- {
- val = Serial.read();
- if (val=='A') {Speed_need=10; Turn_need=0; Serial.println(val);} //前进
- else if(val=='B') {Speed_need=-10; Turn_need=0; Serial.println(val);} //后退
- else if(val=='C') {Speed_need=0; Turn_need=30; Serial.println(val);} //左转
- else if(val=='D') {Speed_need=0; Turn_need=-30; Serial.println(val);} //右转
- else if(val=='Z') {Speed_need=0; Turn_need=0; Serial.println(val);} //直立
- else if(val=='E') {Kp+=1; val = 'Z'; Serial.print("Kp="); Serial.println(Kp);}
- else if(val=='F') {Kp-=1; val = 'Z'; Serial.print("Kp="); Serial.println(Kp);}
- else if(val=='G') {Kd+=0.01;val = 'Z'; Serial.print("Kd="); Serial.println(Kd);}
- else if(val=='H') {Kd-=0.01;val = 'Z'; Serial.print("Kd="); Serial.println(Kd);}
- else if(val=='I') {Ksp+=10; val = 'Z'; Serial.print("Ksp=");Serial.println(Ksp);}
- else if(val=='J') {Ksp-=10; val = 'Z'; Serial.print("Ksp=");Serial.println(Ksp);}
- }
- accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //读MPU6050数据
- Angle_Calcu();
- PWM_Calcu();
- }
复制代码
|