香河英茂工作室 发表于 前天 22:00

zk-5ad没输出原因是?

zk-5ad没输出原因是?

做Arduino uno ,TT电机,MPU6500的自平衡机器人时,烧录程序驱动无输出,什么原因,怎么解决?
由AI8051u擎天柱方案吗?

香河英茂工作室 发表于 前天 22:02

#include "I2Cdev.h"
#include <PID_v1.h> //From https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
#include "MPU6050_6Axis_MotionApps20.h" //https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
MPU6050 mpu;
// MPU control/status vars
bool dmpReady = false;// set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;   // count of all bytes currently in FIFO
uint8_t fifoBuffer; // FIFO storage buffer
// orientation/motion vars
Quaternion q;         //          quaternion container
VectorFloat gravity;    //             gravity vector
float ypr;         //    yaw/pitch/roll container and gravity vector
/*********Tune these 4 values for your BOT*********/
double setpoint= 182; //set the value when the bot is perpendicular to ground using serial monitor.
//Read the project documentation on circuitdigest.com to learn how to set these values
double Kp = 15; //21 Set this first
double Kd = 0.9; //0.8 Set this secound
double Ki = 140; //140 Finally set this
/******End of values setting*********/
double input, output;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
volatile bool mpuInterrupt = false;   // indicates whether MPU interrupt pin has gone high
void dmpDataReady()
{
    mpuInterrupt = true;
}
void setup() {
Serial.begin(115200);
// initialize device
    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();
   // verify connection
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
    // load and configure the DMP
    devStatus = mpu.dmpInitialize();
    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setXGyroOffset(-479);
    mpu.setYGyroOffset(84);
    mpu.setZGyroOffset(15);
    mpu.setZAccelOffset(1638);
      // make sure it worked (returns 0 if so)
    if (devStatus == 0)
    {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);
      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(0, dmpDataReady, RISING);
      mpuIntStatus = mpu.getIntStatus();
      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;
      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
      //setup PID
      pid.SetMode(AUTOMATIC);
      pid.SetSampleTime(10);
      pid.SetOutputLimits(-255, 255);
    }
    else
    {
      // ERROR!
      // 1 = initial memory load failed
      // 2 = DMP configuration updates failed
      // (if it's going to break, usually the code will be 1)
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
    }
//Initialise the Motor outpu pins
    pinMode (6, OUTPUT);
    pinMode (9, OUTPUT);
    pinMode (10, OUTPUT);
    pinMode (11, OUTPUT);
//By default turn off both the motors
    analogWrite(6,LOW);
    analogWrite(9,LOW);
    analogWrite(10,LOW);
    analogWrite(11,LOW);
}
void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;
    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize)
    {
      //no mpu data - performing PID calculations and output to motors   
      pid.Compute();
      //Print the value of Input and Output on serial monitor to check how it is working.
      Serial.print(input); Serial.print(" =>"); Serial.println(output);
      if (input>150 && input<200){//If the Bot is falling
      if (output>0) //Falling towards front
      Forward(); //Rotate the wheels forward
      else if (output<0) //Falling towards back
      Reverse(); //Rotate the wheels backward
      }
      else //If Bot not falling
      Stop(); //Hold the wheels still
    }
    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();
    // get current FIFO count
    fifoCount = mpu.getFIFOCount();
    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024)
    {
      // reset so we can continue cleanly
      mpu.resetFIFO();
      Serial.println(F("FIFO overflow!"));
    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    }
    else if (mpuIntStatus & 0x02)
    {
      // wait for correct available data length, should be a VERY short wait
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
      // read a packet from FIFO
      mpu.getFIFOBytes(fifoBuffer, packetSize);
      // track FIFO count here in case there is > 1 packet available
      // (this lets us immediately read more without waiting for an interrupt)
      fifoCount -= packetSize;
      mpu.dmpGetQuaternion(&q, fifoBuffer); //get value for q
      mpu.dmpGetGravity(&gravity, &q); //get value for gravity
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //get value for ypr
      input = ypr * 180/M_PI + 180;
   }
}
void Forward() //Code to rotate the wheel forward
{
    analogWrite(6,output);
    analogWrite(9,0);
    analogWrite(10,output);
    analogWrite(11,0);
    Serial.print("F"); //Debugging information
}
void Reverse() //Code to rotate the wheel Backward
{
    analogWrite(6,0);
    analogWrite(9,output*-1);
    analogWrite(10,0);
    analogWrite(11,output*-1);
    Serial.print("R");
}
void Stop() //Code to stop both the wheels
{
    analogWrite(6,0);
    analogWrite(9,0);
    analogWrite(10,0);
    analogWrite(11,0);
    Serial.print("S");
}

国芯人工智能 发表于 前天 22:03

在使用Arduino Uno、TT电机、MPU6500构建自平衡机器人时,若出现“zk-5ad无输出”问题,可能涉及硬件连接、传感器数据读取、驱动逻辑或控制算法等多个环节。以下为可能原因及解决方案的系统分析。

一、zk-5ad无输出的可能原因

1. 硬件连接问题
电源供电不足:TT电机功率较大,若电源电压或电流不足,可能导致电机无法驱动。需确保电源电压(如7.4V锂电池)稳定,且Arduino Uno的稳压模块能正常供电。
电机驱动模块故障:若使用L298N或TB6612等驱动模块,需检查模块是否损坏、引脚连接是否正确(如PWM信号线、方向控制线)。
MPU6500通信异常:MPU6500通过I2C接口与Arduino通信,需检查SDA/SCL引脚是否接反、上拉电阻是否缺失或I2C地址是否冲突(默认地址为0x68)。

2. 传感器数据读取失败
MPU6500初始化失败:程序中未正确配置MPU6500寄存器(如电源管理寄存器PWRMGMT1未置零),导致传感器未启动。
数据读取错误:未正确解析MPU6500的加速度计和陀螺仪原始数据,或未进行单位转换(如将陀螺仪数据乘以灵敏度系数)。
滤波算法缺失:未使用互补滤波或卡尔曼滤波融合加速度计和陀螺仪数据,导致角度计算误差过大,影响控制逻辑。

3. 控制逻辑或算法问题
PID参数整定不当:比例(P)、积分(I)、微分(D)系数未合理设置,可能导致系统响应过慢或震荡。例如,P值过小无法纠正倾斜,P值过大则引发剧烈抖动。
输出限幅缺失:电机PWM信号未设置上下限(如analogWrite()范围应为0-255),可能导致输出无效或过载。
方向逻辑错误:电机旋转方向与倾角变化方向未正确对应,例如机器人前倾时电机应向前转动,若方向相反则系统无法平衡。

4. 程序逻辑或代码错误
中断或延时冲突:程序中使用delay()函数可能导致传感器采样间隔过大,影响实时性。建议使用millis()实现非阻塞延时。
变量类型错误:浮点运算未正确声明(如float),或整型溢出导致角度计算错误。
未启用串口调试:未通过Serial.print()输出传感器数据或中间变量,难以定位问题根源。

二、解决方案与调试步骤

1. 硬件排查
使用万用表测量电源电压,确保电机供电充足(如TT电机额定电压为6-12V)。
单独测试电机驱动模块:编写简单程序控制电机正反转,确认驱动模块功能正常。
使用I2C扫描工具(如Arduino IDE的Wire库示例)检测MPU6500是否被正确识别(地址应为0x68)。

2. 传感器调试
编写独立程序读取MPU6500原始数据,验证加速度计和陀螺仪输出是否合理(如静止时加速度Z轴应接近1g)。
实现互补滤波算法,计算倾角并输出至串口,确保角度变化平滑且无漂移。

3. 控制逻辑优化
从简单比例控制(仅P项)开始调试,逐步增加D项抑制震荡,最后加入I项消除稳态误差。
设置PWM输出阈值(如最小值为80,最大值为200),避免电机因输出过小无法启动或过大过载。
通过串口绘图工具(如Arduino Serial Plotter)观察倾角和PWM输出波形,调整PID参数至系统稳定。

4. 代码示例片段
   ```cpp
   // MPU6500初始化
   Wire.beginTransmission(0x68);
   Wire.write(0x6B);// 电源管理寄存器
   Wire.write(0);   // 唤醒传感器
   Wire.endTransmission();

   // 读取传感器数据
   void readMPU() {
   Wire.beginTransmission(0x68);
   Wire.write(0x3B);// 加速度计首地址
   Wire.endTransmission();
   Wire.requestFrom(0x68, 6);
   while (Wire.available() < 6);// 等待数据
   AccX = Wire.read()

[本文内容由国芯人工智能辅助生成,仅供参考]

香河英茂工作室 发表于 昨天 07:03

国芯人工智能 发表于 2025-10-17 22:03
在使用Arduino Uno、TT电机、MPU6500构建自平衡机器人时,若出现“zk-5ad无输出”问题,可能涉及硬件连接、 ...

收到,还是没有找到问题
页: [1]
查看完整版本: zk-5ad没输出原因是?