葱拌豆腐 发表于 2013-4-1 08:58:33

【求助】为啥两轮自横小车老死机

本帖最后由 葱拌豆腐 于 2013-4-2 09:19 编辑

【2012-04-02更新】:查阅了论坛的相关帖子,并研究一下L298N的说明书,现在推测原因如下:第一电机的供电电压不够,根据L298N的手册,电机的供电电压需要大于逻辑电压高电平+2.5v,而我现在电机电压是6v;第二个问题,根据L298N的手册,并联到输出端的二极管必须是快恢复二极管,恢复时间小于200纳秒,而我现在自己用的板子上的二极管是IN4007,普通的整流二极管,查了一下恢复时间大概在2000纳秒左右,差距太多。今天回去先把这两个问题解决掉再试试。

最近折腾了一个两轮自横小车,前些日子刚把角度融合弄好了(计算z轴的角度,陀螺仪计算y轴的旋转,也就是轮子的轴线和y轴平行),昨天把pid和整个程序都写好了,只剩pid参数没有调试,但是测试时,发现运行一段时间就死机了,uno的串口没有输出了,把程序发上来,求各位帮忙给看看啥问题。
电机驱动采用L298N,带隔离,自己写了个库函数。

#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

#include "L298N.h"

L298N::L298N()
{
        _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::L298N(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);
}


=====================以上是L298N的库函数===============================

=====================下面是程序代码==================================

#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;
}


================================================
pid采用了位置式PID,角度融合采用了简单的互补滤波。

另外问个问题,PWM输出的参数是什么类型的?

夏异 发表于 2013-4-1 19:49:02

你的代码没有任何注释,别人很不好看懂的

may_be_maybe 发表于 2013-9-29 23:18:45

楼主啊我加了光耦木有用电机不转共地才转 但是这样会死机    纠结一个星期了   请问你解决了吗怎么弄额?

邵林寺 发表于 2013-9-30 08:36:39

may_be_maybe 发表于 2013-9-29 23:18 static/image/common/back.gif
楼主啊我加了光耦木有用电机不转共地才转 但是这样会死机    纠结一个星期了   请问你解决了吗怎么 ...

你可以等一会看我发的帖子,改一下就行

葱拌豆腐 发表于 2013-9-30 10:45:15

may_be_maybe 发表于 2013-9-29 23:18 static/image/common/back.gif
楼主啊我加了光耦木有用电机不转共地才转 但是这样会死机    纠结一个星期了   请问你解决了吗怎么 ...

换电机吧,我当时用的是香蕉电机,老死机,后来换成22元一个就好了。

may_be_maybe 发表于 2013-10-1 12:35:11

葱拌豆腐 发表于 2013-9-30 10:45 static/image/common/back.gif
换电机吧,我当时用的是香蕉电机,老死机,后来换成22元一个就好了。

这黄色电机太鸡肋了吧   难怪便宜便宜没好货啊浪费我大量精力!但是我看也有人用这种电机做平衡车   很好奇怎么处理死机问题的

may_be_maybe 发表于 2013-10-1 12:39:12

邵林寺 发表于 2013-9-30 08:36 static/image/common/back.gif
你可以等一会看我发的帖子,改一下就行

我共地了。。。低级错误纠结。。。有没有办法一个电源供电呢   两个电池太重哦

邵林寺 发表于 2013-10-1 16:49:38

may_be_maybe 发表于 2013-10-1 12:39 static/image/common/back.gif
我共地了。。。低级错误纠结。。。有没有办法一个电源供电呢   两个电池太重哦

这个没有好办法。或者你可以换个好点的电机,这样杂波干扰会减少
页: [1]
查看完整版本: 【求助】为啥两轮自横小车老死机