本帖最后由 葱拌豆腐 于 2013-4-2 09:19 编辑
【2012-04-02更新】:查阅了论坛的相关帖子,并研究一下L298N的说明书,现在推测原因如下:第一电机的供电电压不够,根据L298N的手册,电机的供电电压需要大于逻辑电压高电平+2.5v,而我现在电机电压是6v;第二个问题,根据L298N的手册,并联到输出端的二极管必须是快恢复二极管,恢复时间小于200纳秒,而我现在自己用的板子上的二极管是IN4007,普通的整流二极管,查了一下恢复时间大概在2000纳秒左右,差距太多。今天回去先把这两个问题解决掉再试试。
最近折腾了一个两轮自横小车,前些日子刚把角度融合弄好了(计算z轴的角度,陀螺仪计算y轴的旋转,也就是轮子的轴线和y轴平行),昨天把pid和整个程序都写好了,只剩pid参数没有调试,但是测试时,发现运行一段时间就死机了,uno的串口没有输出了,把程序发上来,求各位帮忙给看看啥问题。
电机驱动采用L298N,带隔离,自己写了个库函数。
[pre lang="arduino" line="1" file="L298N.H"]
#ifndef _L298N_H
#define _L298N_H
#include <Arduino.h>
class L298N
{
private:
//define control pin of MotorA
unsigned int _MotorACtrPin_1;
unsigned int _MotorACtrPin_2;
float _MotorAPWM;
unsigned int _MotorASpeed;//the range is 0 to 255
unsigned int _MotorAMinSpeed;//define the motor min speed,default is 0
unsigned int _MotorAMaxSpeed;//define the motor max speed,default is 255
//define control pin of MotorB
unsigned int _MotorBCtrPin_1;
unsigned int _MotorBCtrPin_2;
float _MotorBPWM;
unsigned int _MotorBSpeed;//the range is 0 to 255
float _MotorBMinSpeed;
float _MotorBMaxSpeed;
//define turn time,unit is second
unsigned int _TurnTime;
float _TurnSpeed;
public:
//Constructor
L298N();//None parameter
L298N(unsigned int MotorACtrPin_1,unsigned int MotorACtrPin_2,unsigned int MotorAPWM,
unsigned int MotorBCtrPin_1,unsigned int MotorBCtrPin_2,unsigned int MotorBPWM);
void MotorASetSpeedLimit(float minSpeed,float maxSpeed);
void MotorBSetSpeedLimit(float minSpeed,float maxSpeed);
void MotorAForward(float speed);
void MotorAReversal(float speed);
void MotorAStop();
void MotorBForward(float speed);
void MotorBReversal(float speed);
void MotorBStop();
void TurnLeft();
void TurnLeft(unsigned int time,float speed);
void TurnRight();
void TurnRight(unsigned int time,float speed);
};
#endif[/code]
[pre lang="arduino" line="1" file="L298N.cpp"]
#include "L298N.h"
L298N: 298N()
{
_MotorAMinSpeed=0.0;
_MotorAMaxSpeed=255.0;
_MotorBMinSpeed=0.0;
_MotorBMaxSpeed=255.0;
_MotorACtrPin_1=10;
_MotorACtrPin_2=11;
_MotorBCtrPin_1=12;
_MotorBCtrPin_2=13;
_MotorAPWM=5;
_MotorBPWM=6;
pinMode(_MotorACtrPin_1,OUTPUT);
pinMode(_MotorACtrPin_2,OUTPUT);
pinMode(_MotorBCtrPin_1,OUTPUT);
pinMode(_MotorBCtrPin_2,OUTPUT);
digitalWrite(_MotorACtrPin_1,HIGH);
digitalWrite(_MotorACtrPin_2,HIGH);
digitalWrite(_MotorBCtrPin_1,HIGH);
digitalWrite(_MotorBCtrPin_2,HIGH);
}
L298N: 298N(unsigned int motorACtrPin_1,unsigned int motorACtrPin_2,unsigned int motorAPWM,
unsigned int motorBCtrPin_1,unsigned int motorBCtrPin_2,unsigned int motorBPWM)
{
_MotorACtrPin_1=motorACtrPin_1;
_MotorACtrPin_2=motorACtrPin_2;
_MotorBCtrPin_1=motorBCtrPin_1;
_MotorBCtrPin_1=motorBCtrPin_2;
_MotorAPWM=motorAPWM;
_MotorBPWM=motorBPWM;
pinMode(_MotorACtrPin_1,OUTPUT);
pinMode(_MotorACtrPin_2,OUTPUT);
pinMode(_MotorBCtrPin_1,OUTPUT);
pinMode(_MotorBCtrPin_1,OUTPUT);
digitalWrite(_MotorACtrPin_1,HIGH);
digitalWrite(_MotorACtrPin_2,HIGH);
digitalWrite(_MotorBCtrPin_1,HIGH);
digitalWrite(_MotorBCtrPin_1,HIGH);
}
void L298N::MotorASetSpeedLimit(float minSpeed,float maxSpeed)
{
_MotorAMinSpeed=minSpeed;
_MotorBMinSpeed=maxSpeed;
}
void L298N::MotorBSetSpeedLimit(float minSpeed,float maxSpeed)
{
_MotorBMinSpeed=minSpeed;
_MotorBMaxSpeed=maxSpeed;
}
void L298N::MotorAForward(float speed)
{
float mSpeed=speed;
digitalWrite(_MotorACtrPin_1,LOW);
digitalWrite(_MotorACtrPin_2,HIGH);
if(speed<_MotorAMinSpeed)
{
mSpeed=_MotorAMinSpeed;
}
if(speed>_MotorAMaxSpeed)
{
mSpeed=_MotorAMaxSpeed;
}
analogWrite(_MotorAPWM,mSpeed);
}
void L298N::MotorAReversal(float speed)
{
float mSpeed=speed;
digitalWrite(_MotorACtrPin_1,HIGH);
digitalWrite(_MotorACtrPin_2,LOW);
if(speed<_MotorAMinSpeed)
{
mSpeed=_MotorAMinSpeed;
}
if(speed>_MotorAMaxSpeed)
{
mSpeed=_MotorAMaxSpeed;
}
analogWrite(_MotorAPWM,mSpeed);
}
void L298N::MotorAStop()
{
digitalWrite(_MotorACtrPin_1,HIGH);
digitalWrite(_MotorACtrPin_2,HIGH);
}
void L298N::MotorBForward(float speed)
{
float mSpeed=speed;
digitalWrite(_MotorBCtrPin_1,LOW);
digitalWrite(_MotorBCtrPin_2,HIGH);
if(speed<_MotorBMinSpeed)
{
mSpeed=_MotorBMinSpeed;
}
if(speed>_MotorBMaxSpeed)
{
mSpeed=_MotorBMaxSpeed;
}
analogWrite(_MotorBPWM,mSpeed);
}
void L298N::MotorBReversal(float speed)
{
float mSpeed=speed;
digitalWrite(_MotorBCtrPin_1,HIGH);
digitalWrite(_MotorBCtrPin_2,LOW);
if(speed<_MotorBMinSpeed)
{
mSpeed=_MotorBMinSpeed;
}
if(speed>_MotorBMaxSpeed)
{
mSpeed=_MotorBMaxSpeed;
}
analogWrite(_MotorBPWM,mSpeed);
}
void L298N::MotorBStop()
{
digitalWrite(_MotorBCtrPin_1,HIGH);
digitalWrite(_MotorBCtrPin_2,HIGH);
}
void L298N::TurnLeft()
{
//when the car turn left, the left wheel stops and only the right wheel roll forward
//stop the left wheel
digitalWrite(_MotorACtrPin_1,HIGH);
digitalWrite(_MotorACtrPin_2,HIGH);
//the right wheel roll forward
digitalWrite(_MotorBCtrPin_1,LOW);
digitalWrite(_MotorBCtrPin_2,HIGH);
analogWrite(_MotorBPWM,_TurnSpeed);
delay(_TurnTime);
}
void L298N::TurnLeft(unsigned int time,float speed)
{
//when the car turn left, the left wheel stops and only the right wheel roll forward
//stop the left wheel
digitalWrite(_MotorACtrPin_1,HIGH);
digitalWrite(_MotorACtrPin_2,HIGH);
//the right wheel roll forward
digitalWrite(_MotorBCtrPin_1,LOW);
digitalWrite(_MotorBCtrPin_2,HIGH);
analogWrite(_MotorBPWM,speed);
delay(time);
}
void L298N::TurnRight()
{
//when the car turn right, the right wheel stops and only the left wheel roll forward
//stop the right wheel
digitalWrite(_MotorBCtrPin_1,HIGH);
digitalWrite(_MotorBCtrPin_2,HIGH);
//the left wheel roll forward
digitalWrite(_MotorACtrPin_1,LOW);
digitalWrite(_MotorACtrPin_2,HIGH);
analogWrite(_MotorAPWM,_TurnSpeed);
delay(_TurnTime);
}
void L298N::TurnRight(unsigned int time,float speed)
{
//when the car turn right, the right wheel stops and only the left wheel roll forward
//stop the right wheel
digitalWrite(_MotorBCtrPin_1,HIGH);
digitalWrite(_MotorBCtrPin_2,HIGH);
//the left wheel roll forward
digitalWrite(_MotorACtrPin_1,LOW);
digitalWrite(_MotorACtrPin_2,HIGH);
analogWrite(_MotorAPWM,speed);
delay(time);
}
[/code]
=====================以上是L298N的库函数===============================
=====================下面是程序代码==================================
[pre lang="arduino" line="1" file="MyBalanceCar"]
#include <I2Cdev.h>
#include <L298N.h>
#include <MPU6050.h>
#include <Wire.h>
float ax,az,gy;//get acceleration_x,acceleration_z,rotation_y
long OffsetGy,OffsetSum;
float AngleAcc,AngleRotation,AngleMerge;//angel computed by acceleration and rotation
float Kp,Kd,Ki,pid_SP,pid_CV;
float Err,ErrLast,ErrAfter;//PID
long LastTime,NowTime,TimeSpan,SampleTime;//
bool blinkState=false;
L298N l298n;
MPU6050 mpu;
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("start");
mpu.initialize();
Serial.println(mpu.getRotationY());
Serial.println(mpu.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
//compute the gyroscope offset automatic
for(int i=0;i<200;i++)
{
Serial.println(mpu.getRotationY());
OffsetSum=OffsetSum+mpu.getRotationY();
delay(50);
}
OffsetGy=OffsetSum/200;
pid_SP=0.0;
Kp=2.0;
Kd=0.0;
Ki=0.0;
}
void loop()
{
NowTime=millis();
TimeSpan=NowTime-LastTime;
LastTime=NowTime;
MergeAngle();
PID();
if(0.0<AngleMerge)
{
l298n.MotorAForward(pid_CV);
l298n.MotorBForward(pid_CV);
}
if(0.0==AngleMerge)
{
l298n.MotorAForward(0.0);
l298n.MotorBForward(0.0);
}
if(AngleMerge<0.0)
{
l298n.MotorAReversal(pid_CV);
l298n.MotorBReversal(pid_CV);
}
Serial.print(AngleRotation);
Serial.print(",");
Serial.print(AngleMerge);
Serial.print(",");
Serial.println(pid_CV);
delay(100);
}
void PID()
{
ErrAfter=ErrLast;
ErrLast=Err;
Err=pid_SP-AngleMerge;
float deltOut=Kp*Err+Ki*ErrLast+Kd*ErrAfter;
pid_CV=min(255.0,abs(pid_CV+deltOut));
}
void MergeAngle()
{
//compute AngleAcc
ax=mpu.getAccelerationX()/16384.00;
az=mpu.getAccelerationZ()/16384.00;
AngleAcc=(-1.0)*atan2(ax,az)*180/PI;
gy=(mpu.getRotationY()-OffsetGy)/131.00;
AngleRotation=AngleRotation+gy*TimeSpan/1000.00;
AngleMerge=0.8*AngleRotation+0.2*AngleAcc;
}
[/code]
================================================
pid采用了位置式PID,角度融合采用了简单的互补滤波。
另外问个问题,PWM输出的参数是什么类型的? |