一、 Qt设计
采用了C++——Qt设计了炫酷的主页面,里面包含了各类仪表widget,其中有个类似钢铁侠的按钮可以触发和控制平衡小车的蜂鸣器。设计的摇杆按钮可以控制前进、后退、左转、右转、蓝牙连接等功能。
Qt_C++工程: 部分代码:
#ifndef BLE_H
#define BLE_H
#include "Frm_ControlCar.h"
#include <QWidget>
#include <QListWidgetItem>
#include <QtBluetooth/qbluetoothglobal.h>
#include <QtBluetooth/qbluetoothlocaldevice.h>
#include <qbluetoothaddress.h>
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
#include <qbluetoothsocket.h>
#include "Public/typedefine.h"
namespace Ui {
class BLE;
}
class Frm_BLE : public QWidget
{
Q_OBJECT
public:
explicit Frm_BLE(QWidget *parent = 0);
~Frm_BLE();
bool GetBlueState();
void BLE_Write(char data);
void BLE_Read();
private slots:
void on_btn_openBLE_clicked();
void on_btn_upDateBLE_clicked();
void on_btn_return_clicked();
void slotAddBLDeviToList(const QBluetoothDeviceInfo &info);
void slotFindFinish();
void slotClick(QListWidgetItem* item);
void slotConnectBLE();
void slotDisConnectBLE();
void slotConnectOK();
void slotConnectFailed();
private:
Ui::BLE *ui;
QBluetoothSocket *m_BlueSocket;
QBluetoothDeviceDiscoveryAgent *m_discoveryAgent;
QBluetoothLocalDevice *m_localDevice;
QString m_BLName = "";
bool m_bIsConnected = false;
};
#endif
#ifndef FRM_CONTROLCAR_H
#define FRM_CONTROLCAR_H
#include <QWidget>
namespace Ui {
class Frm_ControlCar;
}
class Frm_ControlCar : public QWidget
{
Q_OBJECT
public:
explicit Frm_ControlCar(QWidget *parent = 0);
~Frm_ControlCar();
protected:
void slotDoRockerDirect(int num);
void slotDoScanTan(int num);
private slots:
void on_btnToggleBlueTooth_clicked();
void on_btnInfoFrm_clicked();
private:
Ui::Frm_ControlCar *ui;
};
#endif
二、Stm32平衡小车部分
采用MPU6050六轴传感器,支持蓝牙模块、OLED、减速电机、RBG三色灯等控制,炫酷的钢铁侠开机动画。
更多细节闲鱼搜索平衡小车。代码部分:
#include "control.h"
#include "filter.h"
#include "Stm32_Beep.h"
int Balance_Pwm=0,Velocity_Pwm=0,Turn_Pwm=0;
u8 Flag_Target;
int EXTI4_IRQHandler(void)
{
if(PAin(4)==0)
{
EXTI->PR=1<<4;
gul_softTmr++;
Flag_Target=!Flag_Target;
if(delay_flag==1)
{
if(++delay_50==10)
{
delay_50=0,delay_flag=0;
}
}
if(Flag_Target==1)
{
Get_Angle(Way_Angle);
return 0;
}
Encoder_Left=-Read_Encoder(2);
Encoder_Right=Read_Encoder(4);
Get_Angle(Way_Angle);
if(Bi_zhang==0)
{
}
if(Bi_zhang==1)
{
Led_Flash(1);
}
Key();
Balance_Pwm = balance(Angle_Balance,Gyro_Balance);
Velocity_Pwm = velocity(Encoder_Left,Encoder_Right);
Turn_Pwm = turn(Encoder_Left,Encoder_Right,Gyro_Turn);
Moto1=Balance_Pwm-Velocity_Pwm+Turn_Pwm;
Moto2=Balance_Pwm-Velocity_Pwm-Turn_Pwm;
Xianfu_Pwm();
if(Pick_Up(Acceleration_Z,Angle_Balance,Encoder_Left,Encoder_Right))
{
Flag_Stop=1;
}
if(Put_Down(Angle_Balance,Encoder_Left,Encoder_Right))
{
Flag_Stop=0;
}
if(Turn_Off(Angle_Balance,Voltage)==0)
{
Set_Pwm(Moto1,Moto2);
}
}
return 0;
}
int balance(float Angle,float Gyro)
{
float Bias,kp=480,kd=0.73;
int balance;
Bias=Angle-ZHONGZHI;
balance=kp*Bias+Gyro*kd;
return balance;
}
int velocity(int encoder_left,int encoder_right)
{
static float Velocity,Encoder_Least,Encoder,Movement;
static float Encoder_Integral,Target_Velocity;
float kp=-200,ki=-0.9;
if(Bi_zhang==1&&Flag_sudu==1)
{
Target_Velocity=45;
}
else
{
Target_Velocity=30;
}
if(1==Flag_Qian)
{
Movement=-Target_Velocity/Flag_sudu;
}
else if(1==Flag_Hou)
{
Movement=Target_Velocity/Flag_sudu;
}
else
{
Movement=0;
}
if(Bi_zhang==1 && Distance<500 && Flag_Left!=1 &&Flag_Right!=1)
{
Movement=-Target_Velocity/Flag_sudu;
}
Encoder_Least =(Encoder_Left+Encoder_Right)-0;
Encoder *= 0.8;
Encoder += Encoder_Least*0.2;
Encoder_Integral +=Encoder;
Encoder_Integral=Encoder_Integral-Movement;
if(Encoder_Integral>10000) Encoder_Integral=10000;
if(Encoder_Integral<-10000) Encoder_Integral=-10000;
Velocity=Encoder*kp+Encoder_Integral*ki;
if(Turn_Off(Angle_Balance,Voltage)==1||Flag_Stop==1)
{
Encoder_Integral=0;
}
return Velocity;
}
int turn(int encoder_left,int encoder_right,float gyro)
{
static float Turn_Target,Turn,Encoder_temp,Turn_Convert=0.9,Turn_Count;
float Turn_Amplitude=88/Flag_sudu,Kp=42,Kd=0;
if(1==Flag_Left||1==Flag_Right)
{
if(++Turn_Count==1)
Encoder_temp=myabs(encoder_left+encoder_right);
Turn_Convert=50/Encoder_temp;
if(Turn_Convert<0.6)Turn_Convert=0.6;
if(Turn_Convert>3)Turn_Convert=3;
}
else
{
Turn_Convert=0.9;
Turn_Count=0;
Encoder_temp=0;
}
if(1==Flag_Left) Turn_Target-=Turn_Convert;
else if(1==Flag_Right) Turn_Target+=Turn_Convert;
else Turn_Target=0;
if(Turn_Target>Turn_Amplitude) Turn_Target=Turn_Amplitude;
if(Turn_Target<-Turn_Amplitude) Turn_Target=-Turn_Amplitude;
if(Flag_Qian==1||Flag_Hou==1) Kd=0.5;
else Kd=0;
Turn=-Turn_Target*Kp -gyro*Kd;
return Turn;
}
void Set_Pwm(int moto1,int moto2)
{
if(moto1<0) AIN2=1, AIN1=0;
else AIN2=0, AIN1=1;
PWMA=myabs(moto1);
if(moto2<0) BIN1=0, BIN2=1;
else BIN1=1, BIN2=0;
PWMB=myabs(moto2);
}
void Xianfu_Pwm(void)
{
int Amplitude=6900;
if(Flag_Qian==1) Moto1-=DIFFERENCE;
if(Flag_Hou==1) Moto2+=DIFFERENCE;
if(Moto1<-Amplitude) Moto1=-Amplitude;
if(Moto1>Amplitude) Moto1=Amplitude;
if(Moto2<-Amplitude) Moto2=-Amplitude;
if(Moto2>Amplitude) Moto2=Amplitude;
}
void Key(void)
{
u8 tmp,tmp2;
tmp=click_N_Double(50);
if(tmp==1)
Flag_Stop=!Flag_Stop;
if(tmp==2)
Flag_Show=!Flag_Show;
tmp2=Long_Press();
if(tmp2==1)
Bi_zhang=!Bi_zhang;
}
u8 Turn_Off(float angle, int voltage)
{
u8 temp;
if(angle<-40||angle>40||1==Flag_Stop)
{
temp=1;
AIN1=0;
AIN2=0;
BIN1=0;
BIN2=0;
}
else
{
temp=0;
}
return temp;
}
void Get_Angle(u8 way)
{
float Accel_Y,Accel_X,Accel_Z,Gyro_Y,Gyro_Z;
Temperature=Read_Temperature();
if(way==1)
{
Read_DMP();
Angle_Balance=Roll;
Gyro_Balance=gyro[0];
Gyro_Turn=gyro[2];
Acceleration_Z=accel[2];
}
else
{
Gyro_Y=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_L);
Gyro_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_L);
Accel_X=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_XOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_XOUT_L);
Accel_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_L);
if(Gyro_Y>32768) Gyro_Y-=65536;
if(Gyro_Z>32768) Gyro_Z-=65536;
if(Accel_X>32768) Accel_X-=65536;
if(Accel_Z>32768) Accel_Z-=65536;
Gyro_Balance=-Gyro_Y;
Accel_Y=atan2(Accel_X,Accel_Z)*180/PI;
Gyro_Y=Gyro_Y/16.4;
if(Way_Angle==2) Kalman_Filter(Accel_Y,-Gyro_Y);
else if(Way_Angle==3) Yijielvbo(Accel_Y,-Gyro_Y);
Angle_Balance=angle;
Gyro_Turn=Gyro_Z;
Acceleration_Z=Accel_Z;
}
}
int myabs(int a)
{
int temp;
if(a<0) temp=-a;
else temp=a;
return temp;
}
int Pick_Up(float Acceleration,float Angle,int encoder_left,int encoder_right)
{
static u16 flag,count0,count1,count2;
if(flag==0)
{
if(myabs(encoder_left)+myabs(encoder_right)<30)
{
count0++;
}
else
{
count0=0;
}
if(count0>10)
{
flag=1,count0=0;
}
}
if(flag==1)
{
if(++count1>200)
{
count1=0,flag=0;
}
if(Acceleration>26000&&(Angle>(-20+ZHONGZHI))&&(Angle<(20+ZHONGZHI)))
{
flag=2;
}
}
if(flag==2)
{
if(++count2>100) count2=0,flag=0;
if(myabs(encoder_left+encoder_right)>135)
{
flag=0;
return 1;
}
}
return 0;
}
int Put_Down(float Angle,int encoder_left,int encoder_right)
{
static u16 flag,count;
if(Flag_Stop==0)
return 0;
if(flag==0)
{
if(Angle>(-10+ZHONGZHI)&&Angle<(10+ZHONGZHI)&&encoder_left==0&&encoder_right==0)
flag=1;
}
if(flag==1)
{
if(++count>50)
{
count=0;flag=0;
}
if(encoder_left>=0&&encoder_right>=0&&encoder_left<60&&encoder_right<60)
{
flag=0;
flag=0;
return 1;
}
}
return 0;
}
|