#百人创作先锋团# 基于STM32设计的遥控小车 原创

发布于 2023-1-30 14:21
浏览
0收藏

一、设计要求

智能小车是提前写入预置的控制程序,根据传感器信号反馈完成特定动作的小车。小车可以自主形式、也可以通过手机遥控行驶,在很多领域都在广泛使用。 比如:科学勘探小车、消防灭火小车、快递取件小车、野外动物拍摄场景等等。智能小车能够实时显示时间、速度、里程,具有自动寻迹、寻光、避障功能,可程控行驶速度、准确定位停车,远程传输图像等功能。  


智能小车可以分为三部分——传感器部分、控制器部分、执行器部分。


控制器部分:接收传感器部分传递过来的信号,并根据事前写入的决策系统(软件程序),来决定机器人对外部信号的反应,将控制信号发给执行器部分。好比人的大脑。


执行器部分:驱动机器人做出各种行为,包括发出各种信号(点亮发光二极管、发出声音)的部分,并且可以根据控制器部分的信号调整自己的状态。对机器人小车来说,最基本的就是轮子。这部分就好比人的四肢一样。  


传感器部分:机器人用来读取各种外部信号的传感器,以及控制机器人行动的各种开关。好比人的眼睛、耳朵等感觉器官。


下面介绍一款基于STM32设计的智能小车,支持手机远程遥控形式。


硬件设计:

有硬件小车实物,包含WI-FI模块,电机驱动模块,温度传感器模块等;


软件设计:

1)要求手机端APP控制小车行进方向;

2)小车到指定观测点采集温度和湿度数据后,记录所有

温湿度数据,包含采集时间,地点,温度和湿度;

3)手机端APP可实现实时查看小车当前所在位置温度和湿度,

可实现通过时间,地点查询温度和湿度的功能;实现统计某段时间,观测点温湿度平均值,最高值,最低值等功能;


二、设计总结

上位机设计:

设计一个Android手机APP和一个windows系统端的上位机(语言采用C++ + QT支持跨平台),上位机与小车之间采用WIFI通信;小车上的ESP8266设置为AP模式(路由器模式);上位机需要连接到ESP8266这个WIFI上,方便局域网通信;小车上的ESP8266创建一个TCP服务器,上位机当做TCP客户端,主动连接小车;连接上之后,上位机支持控制小车的方向,前进、后退、左、右、停止;支持显示小车实时上传的温度、湿度、GPS经纬度(室内GPS信号很差)、时间信息(这个时间直接从APP端取)。

可实现通过时间,地点查询温度和湿度的功能;实现统计某段时间,观测点温湿度平均值,最高值,最低值等功能


小车设备:

小车电机驱动模块采用L298N、WIFI模块采用ESP8266、MCU采用STM32F103C8T6、温湿度模块采用DTH11、GPS模块采用北斗GPS+BDS


通信数据格式:

上位机向小车发送指令: a 前进、b后退、c左转、d右转、e停止

小车上上位机发送: #123,456,120.086199,30.139219

分别表示: 温度、湿度、经度、纬度



三、硬件模块

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区


四、小车实物图


#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区


接线示例:

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区


五、APP成品效果图

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

核心代码:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->setWindowTitle("遥控小车上位机");
    SetStyle(":/CarControl.qss");

    connect(&time_p, SIGNAL(timeout()), this, SLOT(time_update()));
    time_p.start(1000);

    /*1. 实例化 QNetworkAccessManager*/
    manager = new QNetworkAccessManager(this);
    /*2. 关联 finished 信号*/
    connect(manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));


    //设置并打开数据库
    if (QSqlDatabase::contains(LOG_IN_DATABASE_CONNECT_NAME))
    {
        database = QSqlDatabase::database(LOG_IN_DATABASE_CONNECT_NAME);
    }
    else
    {
        //数据库类型
        database = QSqlDatabase::addDatabase("QSQLITE",LOG_IN_DATABASE_CONNECT_NAME);
        database.setDatabaseName(LOG_IN_DATABASE_NAME); //数据库名称
        database.setUserName("xl");  //用户名
        database.setPassword("123456"); //
    }

    //打开数据库,如果数据库存在就打开,不存在就自动创建
    if(database.open()==false)
    {
        Log_Text_Display("数据库打开失败.请检查程序运行路径和权限.\n");
    }
    else
    {
        Log_Text_Display("连接数据库成功.\n");
    }

    //数据库:  建表,如果存在就不创建,不存在就创建
    QSqlQuery sql_query(database);
    //下面语句查询名称为CarData 的表是否存在.
    sql_query.exec(QString("select count(*) from sqlite_master where type='table' and name='%1'").arg("CarData"));
    if(sql_query.next())
    {
        if(sql_query.value(0).toInt()==0)
        {
           Log_Text_Display("数据库表是不存在的.准备创建.\n");
           //创建表格 创建表格语句:create table <table_name> (f1 type1, f2 type2,…);
           /* CREATE TABLE 是告诉数据库系统创建一个新表的关键字。
            * CREATE TABLE 语句后跟着表的唯一的名称
            * 或标识*/
           /*下面的语句: 创建一个名称为CarData的表,字段分别是存放 时间、温度、湿度、经度、纬度*/
           QString create_sql = "create table CarData(id int primary key, time varchar(100),temperature varchar(100), humidity varchar(100),longitude varchar(100),latitude varchar(100))";

           sql_query.prepare(create_sql);
           if(!sql_query.exec())
           {
               Log_Text_Display("数据库表创建失败.\n");
           }
           else
           {
               Log_Text_Display("数据库表创建成功.\n");
           }
        }
        else
        {
            Log_Text_Display("数据库表是存在的.不需要创建.\n");
        }
    }

    //显示主页面
     ui->stackedWidget->setCurrentIndex(0);
}


Widget::~Widget()
{
    delete ui;
}

//设置指定样式
void Widget::SetStyle(const QString &qssFile) {
    QFile file(qssFile);
    if (file.open(QFile::ReadOnly)) {
        QString qss = QLatin1String(file.readAll());
        qApp->setStyleSheet(qss);
        QString PaletteColor = qss.mid(20, 7);
        qApp->setPalette(QPalette(QColor(PaletteColor)));
        file.close();
    }
}


/*
工程: SmartHome
日期: 2021-04-26
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 日志显示
*/
void Widget::Log_Text_Display(QString text)
{
    QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit_log;
    //设置光标到文本末尾
    plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
    //当文本数量超出一定范围就清除
    if(plainTextEdit_log->toPlainText().size()>1024*4)
    {
        plainTextEdit_log->clear();
    }
    plainTextEdit_log->insertPlainText(text);
    //移动滚动条到底部
    QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
    if(scrollbar)
    {
        scrollbar->setSliderPosition(scrollbar->maximum());
    }
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 连接服务器
*/
void Widget::on_pushButton_connect_clicked()
{
    if(ui->pushButton_connect->text()=="连接"){

        //开始连接服务器
        NewClinet();
    }
    else
    {
        if(LocalTcpClientSocket)
        {
            LocalTcpClientSocket->close();
        }
    }
}

//客户端模式:创建客户端
void Widget::NewClinet()
{
    if(LocalTcpClientSocket)
    {
        LocalTcpClientSocket->close();
        delete  LocalTcpClientSocket;
        LocalTcpClientSocket=nullptr;
    }
    /*1. 创建本地客户端TCP套接字*/
    LocalTcpClientSocket = new QTcpSocket;
    /*2. 设置服务器IP地址*/
    QString Ipaddr=ui->lineEdit_ip->text();
    QHostAddress FarServerAddr(Ipaddr);
    /*3. 连接客户端的信号槽*/
    connect(LocalTcpClientSocket,SIGNAL(connected()),this,SLOT(LocalTcpClientConnectedSlot()));
    connect(LocalTcpClientSocket,SIGNAL(disconnected()),this,SLOT(LocalTcpClientDisconnectedSlot()));
    connect(LocalTcpClientSocket,SIGNAL(readyRead()),this,SLOT(LocalTcpClientReadDtatSlot()));
    /*4. 尝试连接服务器主机*/
    int prot=ui->lineEdit_port->text().toInt();
    LocalTcpClientSocket->connectToHost(FarServerAddr,prot);
}


//客户端模式:响应连接上服务器之后的操作
void Widget::LocalTcpClientConnectedSlot()
{
    ui->pushButton_connect->setText("断开");
    Log_Text_Display("成功连接服务器...\n");
}

//客户端模式:断开服务器
void Widget::LocalTcpClientDisconnectedSlot()
{
   ui->pushButton_connect->setText("连接");
   Log_Text_Display("与服务器断开连接...\n");
}

//客户端模式:读取服务器发过来的数据
//温湿度:  #123,456,120.086199,30.139219
//分别表示: 温度、湿度、经度、纬度
void Widget::LocalTcpClientReadDtatSlot()
{
   QString array=LocalTcpClientSocket->readAll();

   QDateTime time = QDateTime::currentDateTime();   //获取系统现在的时间
   QString   time_str = time.toString("yyyy-MM-dd hh:mm:ss"); //设置显示格式

   QString text;

   text +=array;
   text +="\n";

   Log_Text_Display(text);

   //解析数据
   if(array.at(0)=='#')
   {
       array.remove('#');
       QString T_str=array.section(',',0,0); //温度
       QString H_str=array.section(',',1,1);  //湿度
       QString jin_str=array.section(',',2,2);  //经度
       QString wei_str=array.section(',',3,4);  //纬度

       ui->label_H->setText(H_str+"%");
       ui->label_Temp->setText(T_str+"℃");
       ui->label_latitude->setText(wei_str);
       ui->label_longitude_jin->setText(jin_str);

       //保存数据到数据库
       QSqlQuery sql_query(database);

       //查询最大ID
       QString select_max_sql = "select max(id) from CarData";
       int max_id = 0;
       sql_query.prepare(select_max_sql);
       if(!sql_query.exec())
       {
           Log_Text_Display("数据库最大ID查找失败.\n");
       }
       else
       {
           while(sql_query.next())
           {
               max_id = sql_query.value(0).toInt();
           }
           Log_Text_Display(QString("data base max id:%1\n").arg(max_id));

           //添加数据
           //插入数据 插入语句:insert into <table_name> values (value1, value2,…);
           QString insert_sql = tr("insert into CarData values(?,?,?,?,?,?)");
           sql_query.prepare(insert_sql);
           sql_query.addBindValue(max_id+1); //id
           sql_query.addBindValue(time_str); //时间
           sql_query.addBindValue(T_str);    //温度
           sql_query.addBindValue(H_str);    //湿度
           sql_query.addBindValue(jin_str);  //经度
           sql_query.addBindValue(wei_str);  //纬度
           if(!sql_query.exec())
           {
              Log_Text_Display("数据插入失败.\n");
           }
       }
   }
}


/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 主页面
*/
void Widget::on_pushButton_home_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);
}


/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 小车地图
*/
void Widget::on_pushButton_map_clicked()
{
    ui->stackedWidget->setCurrentIndex(1);
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 历史数据
*/
void Widget::on_pushButton_data_history_clicked()
{
    QDateTime time = QDateTime::currentDateTime();   //获取系统现在的时间
    //设置截止时间
    ui->dateTimeEdit_end->setDateTime(time);

    ui->stackedWidget->setCurrentIndex(2);
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 前进
*/
void Widget::on_pushButton_qianjin_clicked()
{
    if(LocalTcpClientSocket)LocalTcpClientSocket->write("a");
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 后退
*/
void Widget::on_pushButton_houtui_clicked()
{
    if(LocalTcpClientSocket)LocalTcpClientSocket->write("b");
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 左
*/
void Widget::on_pushButton_zuo_clicked()
{
    if(LocalTcpClientSocket)LocalTcpClientSocket->write("c");
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 右
*/
void Widget::on_pushButton_you_clicked()
{
    if(LocalTcpClientSocket)LocalTcpClientSocket->write("d");
}

/*
工程: CarControl
日期: 2021-04-27
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 停止
*/
void Widget::on_pushButton_stop_clicked()
{
   if(LocalTcpClientSocket)LocalTcpClientSocket->write("e");
}

/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 时间更新
*/
void Widget::time_update()
{
   QDateTime time = QDateTime::currentDateTime();   //获取系统现在的时间
   QString text;
   text = time.toString("yyyy/MM/dd hh:mm:ss ddd"); //设置显示格式
   ui->label_time->setText(text);

}


/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: QNetworkReply 返回值处理
*/
void Widget::replyFinished(QNetworkReply*network)
{
    //无错误返回
    if(network->error() == QNetworkReply::NoError)
    {
        //读取所有数据
        QByteArray byte_array=network->readAll();
        QPixmap pixmap;
        //加载图片
        if(pixmap.loadFromData(byte_array,"png",Qt::AutoColor))
        {
            //QPixmap scaledPixmap = pixmap.scaled(ui->label_MapDisplay->size(), Qt::KeepAspectRatio);
            //ui->label_MapDisplay->setScaledContents(true);
            ui->label_MapDisplay->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);
            ui->label_MapDisplay->setPixmap(pixmap);
        }
    }else
    {
        QMessageBox::warning(this, tr("错误信息提示"),tr("更新地图失败.\n""检查网络是否正常!"),
                             QMessageBox::Ok);
    }
    //删除 reply, 不能在 repyfinished 里直接 delete,要调用 deletelater;
    network->deleteLater();
}

/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 更新地图显示
*/
void Widget::on_pushButton_update_map_clicked()
{
    QString type;

    if(ui->radioButton_bd0911->isChecked())type="bd09ll";
    if(ui->radioButton_bd09mc->isChecked())type="bd09mc";
    if(ui->radioButton_gcj0211->isChecked())type="gcj02ll";
    if(ui->radioButton_wgs8411->isChecked())type="wgs84ll";
    QString url=QString("http://api.map.baidu.com/staticimage/v2?ak=CtgpfPgQrtkFfaK27XgXtSKG88Fva8zQ&width=400&height=800¢er=&markers=%1,%2&zoom=%3&markerS&coordtype=%4")
            .arg(ui->label_longitude_jin->text()).arg(ui->label_latitude->text()).arg(ui->horizontalSlider->value()).arg(type);
    /*3. 提交请求*/
    manager->get(QNetworkRequest(QUrl(url)));
}


/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 清空数据库
*/
void Widget::on_pushButton_clean_data_clicked()
{
    QString cmd;
    cmd = QString("delete from CarData");
    QSqlQuery sql_query(database);
    if(!sql_query.exec(cmd))
    {
        Log_Text_Display("delete table Error.\n");
    }
}

/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 历史最高温度
*/
void Widget::on_pushButton_tempH_clicked()
{
    //指定操作的数据库
    QSqlQuery sql_query(database);
    //查询全部数据
    sql_query.prepare("select * from CarData");
    if(!sql_query.exec())
    {
        Log_Text_Display("数据库查询错误.\n");
    }
    else
    {
        QString T_max_time; //最高温度所在的时间
        double T_max=ui->label_Temp->text().toInt(); //最高温度
        double t_tmp=0; //当前温度

        QString H_max_time; //最高湿度所在的时间
        double H_max=ui->label_H->text().toInt(); //最高湿度
        double h_tmp=0; //当前湿度

        while(sql_query.next())
        {
           // int id = sql_query.value(0).toInt(); //ID
            QString time = sql_query.value(1).toString(); //时间
            QString T_str = sql_query.value(2).toString(); //温度
            QString H_str = sql_query.value(3).toString(); //湿度
            QString jin_str = sql_query.value(4).toString(); //经度
            QString wei_str = sql_query.value(5).toString(); //纬度

            //比较温度
            t_tmp=T_str.toDouble();
            if(t_tmp>T_max)
            {
                T_max=t_tmp;
                T_max_time=time;
            }

            //比较湿度
            h_tmp=H_str.toDouble();
            if(h_tmp>H_max)
            {
                H_max=h_tmp;
                H_max_time=time;
            }
        }

        QString show_text=QString("最高温度:%1,时间:%2\n").arg(T_max).arg(T_max_time);
        show_text+=QString("最高湿度:%1,时间:%2\n").arg(H_max).arg(H_max_time);

        QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit_temp_data;
        //设置光标到文本末尾
        plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
        //当文本数量超出一定范围就清除
        if(plainTextEdit_log->toPlainText().size()>1024*4)
        {
            plainTextEdit_log->clear();
        }
        plainTextEdit_log->insertPlainText(show_text);
        //移动滚动条到底部
        QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
        if(scrollbar)
        {
            scrollbar->setSliderPosition(scrollbar->maximum());
        }
    }
}

/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 历史最低温度
*/
void Widget::on_pushButton_tempL_clicked()
{
    //指定操作的数据库
    QSqlQuery sql_query(database);
    //查询全部数据
    sql_query.prepare("select * from CarData");
    if(!sql_query.exec())
    {
        Log_Text_Display("数据库查询错误.\n");
    }
    else
    {
        QString T_min_time; //最低温度所在的时间
        double T_min; //最低温度
        double t_tmp; //当前温度

        QString H_min_time; //最低湿度所在的时间
        double H_min; //最低湿度
        double h_tmp; //当前湿度

        sql_query.next();
        QString time = sql_query.value(1).toString(); //时间
        QString T_str = sql_query.value(2).toString(); //温度
        QString H_str = sql_query.value(3).toString(); //湿度
        QString jin_str = sql_query.value(4).toString(); //经度
        QString wei_str = sql_query.value(5).toString(); //纬度

        T_min=T_str.toDouble();
        H_min=H_str.toDouble();
        T_min_time=time;
        H_min_time=time;

        while(sql_query.next())
        {
           // int id = sql_query.value(0).toInt(); //ID
            time = sql_query.value(1).toString(); //时间
            T_str = sql_query.value(2).toString(); //温度
            H_str = sql_query.value(3).toString(); //湿度
            jin_str = sql_query.value(4).toString(); //经度
            wei_str = sql_query.value(5).toString(); //纬度

            //比较温度
            t_tmp=T_str.toDouble();
            if(t_tmp<T_min)
            {
                T_min=t_tmp;
                T_min_time=time;
            }

            //比较湿度
            h_tmp=H_str.toDouble();
            if(h_tmp<H_min && h_tmp>0)
            {
                H_min=h_tmp;
                H_min_time=time;
            }
        }

        QString show_text=QString("最低温度:%1,时间:%2\n").arg(T_min).arg(T_min_time);
        show_text+=QString("最低湿度:%1,时间:%2\n").arg(H_min).arg(H_min_time);

        QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit_temp_data;
        //设置光标到文本末尾
        plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
        //当文本数量超出一定范围就清除
        if(plainTextEdit_log->toPlainText().size()>1024*4)
        {
            plainTextEdit_log->clear();
        }
        plainTextEdit_log->insertPlainText(show_text);
        //移动滚动条到底部
        QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
        if(scrollbar)
        {
            scrollbar->setSliderPosition(scrollbar->maximum());
        }
    }
}


/*
工程: CarControl
日期: 2021-04-28
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 时间范围查询
*/
void Widget::on_pushButton_TimeQuery_clicked()
{
    //指定操作的数据库
    QSqlQuery sql_query(database);
    //查询全部数据
    sql_query.prepare("select * from CarData");
    if(!sql_query.exec())
    {
        Log_Text_Display("数据库查询错误.\n");
    }
    else
    {
        QString T_max_time; //最高温度所在的时间
        double T_max; //最高温度
        double t_tmp; //当前温度

        QString H_max_time; //最高湿度所在的时间
        double H_max; //最高湿度
        double h_tmp; //当前湿度

        QString T_min_time; //最低温度所在的时间
        double T_min; //最低温度
        double t_tmp2; //当前温度

        QString H_min_time; //最低湿度所在的时间
        double H_min; //最低湿度
        double h_tmp2; //当前湿度

        sql_query.next();
        QString time = sql_query.value(1).toString(); //时间
        QString T_str = sql_query.value(2).toString(); //温度
        QString H_str = sql_query.value(3).toString(); //湿度
        QString jin_str = sql_query.value(4).toString(); //经度
        QString wei_str = sql_query.value(5).toString(); //纬度

        T_min=T_str.toDouble();
        H_min=H_str.toDouble();
        T_max=T_str.toDouble();
        H_max=T_str.toDouble();
        T_min_time=time;
        H_min_time=time;
        T_max_time=time;
        H_max_time=time;

        while(sql_query.next())
        {
           // int id = sql_query.value(0).toInt(); //ID
            time = sql_query.value(1).toString(); //时间
            T_str = sql_query.value(2).toString(); //温度
            H_str = sql_query.value(3).toString(); //湿度
            jin_str = sql_query.value(4).toString(); //经度
            wei_str = sql_query.value(5).toString(); //纬度

            int year=time.mid(0,4).toInt();  //年
            int month=time.mid(5,2).toInt();  //月
            int day=time.mid(8,2).toInt(); //日

            QDate start_date=ui->dateTimeEdit_start->date();
            QDate end_date=ui->dateTimeEdit_end->date();

            //判断年范围
            if(year<start_date.year() || year >end_date.year())continue;
            //判断月范围
            if(month<start_date.month() || month >end_date.month())continue;
            //判断日范围
            if(day<start_date.day() || day >end_date.day())continue;

            //比较温度
            t_tmp=T_str.toDouble();
            if(t_tmp>T_max)
            {
                T_max=t_tmp;
                T_max_time=time;
            }

            //比较湿度
            h_tmp=H_str.toDouble();
            if(h_tmp>H_max && h_tmp>0)
            {
                H_max=h_tmp;
                H_max_time=time;
            }

            //比较温度
            t_tmp2=T_str.toDouble();
            if(t_tmp2<T_min && t_tmp2>0)
            {
                T_min=t_tmp2;
                T_min_time=time;
            }

            //比较湿度
            h_tmp2=H_str.toDouble();
            if(h_tmp2<H_min && h_tmp2>0)
            {
                H_min=h_tmp2;
                H_min_time=time;
            }
        }

        QString show_text=QString("最高温度:%1,时间:%2\n").arg(T_max).arg(T_max_time);
        show_text+=QString("最高湿度:%1,时间:%2\n").arg(H_max).arg(H_max_time);

        show_text+=QString("最低温度:%1,时间:%2\n").arg(T_min).arg(T_min_time);
        show_text+=QString("最低湿度:%1,时间:%2\n").arg(H_min).arg(H_min_time);

        QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit_temp_data;
        //设置光标到文本末尾
        plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
        //当文本数量超出一定范围就清除
        if(plainTextEdit_log->toPlainText().size()>1024*4)
        {
            plainTextEdit_log->clear();
        }
        plainTextEdit_log->insertPlainText(show_text);
        //移动滚动条到底部
        QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
        if(scrollbar)
        {
            scrollbar->setSliderPosition(scrollbar->maximum());
        }
    }
}


/*
工程: CarControl
日期: 2021-04-29
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 查询所有数据
*/
void Widget::on_pushButton_all_data_clicked()
{
    //指定操作的数据库
    QSqlQuery sql_query(database);
    //查询全部数据
    sql_query.prepare("select * from CarData");
    if(!sql_query.exec())
    {
        Log_Text_Display("数据库查询错误.\n");
    }
    else
    {
        while(sql_query.next())
        {
           // int id = sql_query.value(0).toInt(); //ID
            QString time = sql_query.value(1).toString(); //时间
            QString T_str = sql_query.value(2).toString(); //温度
            QString H_str = sql_query.value(3).toString(); //湿度
            QString jin_str = sql_query.value(4).toString(); //经度
            QString wei_str = sql_query.value(5).toString(); //纬度

            QString show_text=QString("%1,%2℃,%3%\n").arg(time).arg(T_str).arg(H_str);
            QPlainTextEdit *plainTextEdit_log=ui->plainTextEdit_temp_data;
            //设置光标到文本末尾
            plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
            plainTextEdit_log->insertPlainText(show_text);
            //移动滚动条到底部
            QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
            if(scrollbar)
            {
                scrollbar->setSliderPosition(scrollbar->maximum());
            }
        }
    }
}

/*
工程: CarControl
日期: 2021-04-29
作者: DS小龙哥
环境: win10 QT5.12.6 MinGW32
功能: 清空显示
*/
void Widget::on_pushButton_clean_clicked()
{
    ui->plainTextEdit_temp_data->clear();
}


六、程序下载

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区


#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区

#百人创作先锋团# 基于STM32设计的遥控小车-汽车开发者社区


STM32核心代码(电机控制部分):

#include "motor.h"

//全局变量定义
unsigned int speed_count=0;//占空比计数器 50次一周期
int front_left_speed_duty=SPEED_DUTY;
int front_right_speed_duty=SPEED_DUTY;
int behind_left_speed_duty=SPEED_DUTY;
int behind_right_speed_duty=SPEED_DUTY;


unsigned char continue_time=0;


//根据占空比驱动电机转动
void CarMove(void)
{   
	 BEHIND_RIGHT_EN;
		//右前轮
	if(front_right_speed_duty > 0)//向前
	{
		if(speed_count < front_right_speed_duty)
		{
			FRONT_RIGHT_GO;
		}else                //停止
		{
			FRONT_RIGHT_STOP;
		}
	}
	else if(front_right_speed_duty < 0)//向后
	{
		if(speed_count < (-1)*front_right_speed_duty)
		{
			FRONT_RIGHT_BACK;
		}else                //停止
		{
			FRONT_RIGHT_STOP;
		}
	}
	else                //停止
	{
		FRONT_RIGHT_STOP;
	}
	
	//左后轮
	if(behind_left_speed_duty > 0)//向前
	{
		if(speed_count < behind_left_speed_duty)
		{
			BEHIND_LEFT_GO;
		}	else                //停止
		{
			BEHIND_LEFT_STOP;
		}
	}
	else if(behind_left_speed_duty < 0)//向后
	{
		if(speed_count < (-1)*behind_left_speed_duty)
		{
			BEHIND_LEFT_BACK;
		}	else                //停止
		{
			BEHIND_LEFT_STOP;
		}
	}
	else                //停止
	{
		BEHIND_LEFT_STOP;
	}
}


//向前
void CarGo(void)
{
	front_left_speed_duty=SPEED_DUTY;
	front_right_speed_duty=SPEED_DUTY;
	behind_left_speed_duty=SPEED_DUTY;
	behind_right_speed_duty=SPEED_DUTY;
}

//后退
void CarBack(void)
{
	front_left_speed_duty=-SPEED_DUTY;
	front_right_speed_duty=-SPEED_DUTY;
	behind_left_speed_duty=-SPEED_DUTY;
	behind_right_speed_duty=-SPEED_DUTY;
}

//向左
void CarLeft(void)
{
	front_left_speed_duty=-20;
	front_right_speed_duty=SPEED_DUTY;
	behind_left_speed_duty=-20;
	behind_right_speed_duty=SPEED_DUTY+10;//增加后轮驱动力
}

//向右
void CarRight(void)
{
	front_left_speed_duty=SPEED_DUTY;
	front_right_speed_duty=-20;
	behind_left_speed_duty=SPEED_DUTY+10;//增加后轮驱动力
	behind_right_speed_duty=-20;
}

//停止
void CarStop(void)
{
	front_left_speed_duty=0;
	front_right_speed_duty=0;
	behind_left_speed_duty=0;
	behind_right_speed_duty=0;
}



/*
FRONT_LEFT_F_PIN	PG13	左前前进IO
FRONT_LEFT_B_PIN	PG11	左前后退IO

FRONT_RIGHT_F_PIN	PC11	右前前进IO
FRONT_RIGHT_B_PIN	PD0	  右前后退IO

BEHIND_LEFT_F_PIN	PD6	    左后前进IO
BEHIND_LEFT_B_PIN	PG9	    左后后退IO

右后电机的两个控制IO这里改为两路使能EN1、EN2,高电平有效
BEHIND_RIGHT_F_PIN	PD4	    右电机使能IO
BEHIND_RIGHT_B_PIN	PD2	    左电机使能IO
*/
void MotorInit(void)
{
	RCC->APB2ENR|=1<<8; //PG
	RCC->APB2ENR|=1<<5; //PD
    RCC->APB2ENR|=1<<4; //PC
    
    GPIOG->CRH&=0xFF0F0F0F;
    GPIOG->CRH|=0x00303030;
    
    GPIOD->CRL&=0xF0F0F0F0;
    GPIOD->CRL|=0x03030303;
    
    GPIOC->CRH&=0xFFFF0FFF;
    GPIOC->CRH|=0x00003000;
    
	CarStop();

}



©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
相关推荐