极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11384|回复: 2

Arduino自平衡小车的问题,恳请各位帮忙

[复制链接]
发表于 2012-6-23 08:42:08 | 显示全部楼层 |阅读模式
小弟才接触Arduino
最近想做一个Arduino自平衡小车  有一块UNO
三轴角加速度传感器用ADXL335       陀螺仪用IDG300        电机采用Pololu的29:1减速电机( 用串口传输方式进行调速,范围0~127)
控制思路采用卡尔曼滤波+PID控制的方法
但是遇到两个问题
第一是卡尔曼滤波后发现计算所得的角度值有一定的滞后
其次是在调试PID参数Kp时发现小车在晃动的同时会不由自主的变快最后无法控制,不知这是否和卡尔曼滤波没有处理好有关
想请各位大侠帮忙,能否告知一二
一下是我的代码(PID参数还未设定):
#include <SoftwareSerial.h>
#include <math.h>

SoftwareSerial mySerial(5, 6);
const int xpin = A0;                  // x-axis of the accelerometer
const int ypin = A1;                  // y-axis
const int zpin = A2;                  // z-axis (only on 3-axis models)
const int x_gyro = A4;
int e, motor_speed, x_g;
long z_average, y_average;
float z_acc, angle_sum, y_acc, x_rate;
double Kp, Ki,Kd, angle_acc, actAngle0, actAngle;
int sensorValue[2]  = { 0, 0}; //y,z accelerameter
int sensorZero[2]   = { 336, 340}; //y,z accelerameter

int STD_LOOP_TIME = 9;
int lastLoopTime = STD_LOOP_TIME;
int lastLoopUsefulTime = STD_LOOP_TIME;
unsigned long loopStartTime = 0;

void setup()
{
  Serial.begin(9600);
/***************电机初始化******************/
  mySerial.begin(19200);
  mySerial.write(0xAA);
  mySerial.write(0x88);
  mySerial.write(127);
  mySerial.write(0xAA);
  mySerial.write(0x8E);
  mySerial.write(127);
/*********************************************/
  Kp = 0;
  Ki = 0;
  Kd = 0;
}

void loop()
{
  getangle_accelerameter();
  getangle_gyro();
  
  lastLoopUsefulTime = millis()-loopStartTime;
  if(lastLoopUsefulTime<STD_LOOP_TIME)         
  delay(STD_LOOP_TIME-lastLoopUsefulTime);
  lastLoopTime = millis() - loopStartTime;
  loopStartTime = millis();
  actAngle = kalmanCalculate(angle_acc, x_rate, lastLoopTime);
  /*******************PID算法**************************/
  e = actAngle - actAngle0;
  angle_sum += actAngle;
   actAngle0 = actAngle;
  if (angle_sum>50) angle_sum = 50;
  if (angle_sum<-50) angle_sum = -50;
  motor_speed = (Kp * actAngle) + (Ki * angle_sum) + (Kd * e);
/*****************************************************/
  
  if(motor_speed > 0)  //run forward
  {
    motor_speed = motor_speed;
    mySerial.write(0x8A);
    mySerial.write(motor_speed);
    mySerial.write(0x8C);
    mySerial.write(motor_speed);
  }
  if(motor_speed < 0)  //run backward
  {
    motor_speed = 0 - motor_speed;
    mySerial.write(0x88);
    mySerial.write(motor_speed);
    mySerial.write(0x8E);
    mySerial.write(motor_speed);
  }
  
}

void getangle_accelerameter()
{
  y_average = 0;
  z_average = 0;
  for(int i=0;i<15;i++)
  {
    for(int n=0;n<2;n++)
    sensorValue[n]=analogRead(n+1)-sensorZero[n];
    y_average = y_average + sensorValue[0];
    z_average = z_average + sensorValue[1];
  }
  y_acc = y_average / 15.0;
  z_acc = z_average / 15.0;
  angle_acc = atan(z_acc/y_acc) * 180 / 3.14 - 2;
}

void getangle_gyro()
{
  x_g = analogRead(4);
  x_rate = (x_g - 308) * 2.44;
}
/*************************卡尔曼滤波(从网上参考的)**************/
    float Q_angle  =  0.001;
    float Q_gyro   =  0.003;
    float R_angle  =  0.03;

    float x_angle = 0;
    float x_bias = 0;
    float P_00 = 0, P_01 = 0, P_10 = 0, P_11 = 0;
    float dt, y, S;
    float K_0, K_1;

  float kalmanCalculate(float newAngle, float newRate,int looptime)
  {
    dt = float(looptime)/1000;
    x_angle += dt * (newRate - x_bias);
    P_00 +=  - dt * (P_10 + P_01) + Q_angle * dt;
    P_01 +=  - dt * P_11;
    P_10 +=  - dt * P_11;
    P_11 +=  + Q_gyro * dt;

    y = newAngle - x_angle;
    S = P_00 + R_angle;
    K_0 = P_00 / S;
    K_1 = P_10 / S;

    x_angle +=  K_0 * y;
    x_bias  +=  K_1 * y;
    P_00 -= K_0 * P_00;
    P_01 -= K_0 * P_01;
    P_10 -= K_1 * P_00;
    P_11 -= K_1 * P_01;

    return x_angle;
  }
回复

使用道具 举报

发表于 2012-9-15 07:28:23 | 显示全部楼层
不懂,帮忙顶顶
回复 支持 反对

使用道具 举报

发表于 2013-12-26 00:58:09 | 显示全部楼层
kalman滤波后,角度反应太慢了。
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-10 05:54 , Processed in 0.037592 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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