极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14184|回复: 8

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

[复制链接]
发表于 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,带隔离,自己写了个库函数。
[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输出的参数是什么类型的?
回复

使用道具 举报

发表于 2013-4-1 19:49:02 | 显示全部楼层
你的代码没有任何注释,别人很不好看懂的
回复 支持 反对

使用道具 举报

发表于 2013-9-29 23:18:45 | 显示全部楼层
楼主啊  我加了光耦木有用  电机不转  共地才转 但是这样会死机    纠结一个星期了   请问你解决了吗  怎么弄额?
回复 支持 反对

使用道具 举报

发表于 2013-9-30 08:36:39 | 显示全部楼层
may_be_maybe 发表于 2013-9-29 23:18
楼主啊  我加了光耦木有用  电机不转  共地才转 但是这样会死机    纠结一个星期了   请问你解决了吗  怎么 ...

你可以等一会看我发的帖子,改一下就行
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-30 10:45:15 | 显示全部楼层
may_be_maybe 发表于 2013-9-29 23:18
楼主啊  我加了光耦木有用  电机不转  共地才转 但是这样会死机    纠结一个星期了   请问你解决了吗  怎么 ...

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

使用道具 举报

发表于 2013-10-1 12:35:11 | 显示全部楼层
葱拌豆腐 发表于 2013-9-30 10:45
换电机吧,我当时用的是香蕉电机,老死机,后来换成22元一个就好了。

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

使用道具 举报

发表于 2013-10-1 12:39:12 | 显示全部楼层
邵林寺 发表于 2013-9-30 08:36
你可以等一会看我发的帖子,改一下就行

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

使用道具 举报

发表于 2013-10-1 16:49:38 | 显示全部楼层
may_be_maybe 发表于 2013-10-1 12:39
我共地了。。。  低级错误  纠结。。。  有没有办法一个电源供电呢   两个电池太重哦

这个没有好办法。或者你可以换个好点的电机,这样杂波干扰会减少
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-5 21:49 , Processed in 0.037151 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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