1436|3

29

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【基于树莓派教育套件的物联网开发】项目提交 [复制链接]

  本帖最后由 eew_7QI3Yq 于 2022-10-17 15:02 编辑

 

作品名称

基于树莓派教育套件的物联网开发

                                                                                                                                                                                                                            作者:eew_7QI3Yq        

  • 作品简介

本次大赛申请了树莓派作为我们的物联网开发套件,其主要是借助了树莓派的强大生态,以及用户群体众多的好处,树莓派可以实现我们的图像开发,可以直接添加好我们的QT,然后做界面处理,还可以使用QT调用OPENCV来运行,本身也可以直接做相关开发,极大的简化了我们的开发流程,同时网上的教程也很多,所以非常适合我们的开发工作。我作为申请了物联网开发,我在其中通过QT 的MQTT模块,进行了阿里云连接,上传数据,同时通过阿里云平台进行下发控制数据,可以控制我们底层的LED灯状态。

二、系统框图

 

整体框图如上,硬件部分全部通过树莓派400的拓展接口连接,软件通过树莓派系统中安装QT,进行桌面端的开发工作。后续自己也想通过学习OPENCV和QT之间进行一些图像识别功能处理。

三、各部分功能说明

 

主要的三个传感器,一个PM2.5激光传感器,一个SHT20温湿度传感器,一个SGP30 TVOC和CO2传感器。

 

给树莓派400的一个拓展接口板子,还有一个LED灯设备。

 

整体图片,主题是树莓派400,一个键盘形式的开发板,省去了我们外接键盘非常好用,就是hdmi接口需要购买一个单独的线,进行转接输出。

 

显示屏幕上我,做了QT开发的方案,里面可以直接运行程序然后读取底层三个传感器的数值,同时控制一个按键作为底层灯亮灭的功能。还有一部分是做了摄像头采集图像功能,可以实时显示画面的。

  • 作品源码
 QString host("iot-06z00ac7lu605si.mqtt.iothub.aliyuncs.com"); // 代理服务器 IP

 QByteArray password = xxxx; // 设备密码

 quint16 port = 1883; // 代理服务器端口

 QString ClientId = xxxx; // 设备 ID

 QString productId = "qt_test&h14lBOv58fr";   // 产品 ID



 client->setKeepAlive(120); // 心跳

 client->setHostName(host); // 设置 EMQ 代理服务器

 client->setPort(port); // 设置 EMQ 代理服务器端口

 client->setClientId(ClientId); // 设备 ID

 client->setUsername(productId); // 产品 ID

 client->setPassword(password);

 client->cleanSession();

 client->setVersion(QMQTT::MQTTVersion::V3_1_1); // 设置mqtt版本



 client->connectToHost(); // 连接 EMQ 代理服务器

 

整体连接阿里云服务器就是上面的代码,我们只需要设置好服务器的网址,这个是阿里云统一的华东服务器的网址。后面的设备密码,代理服务器端口,ID都是需要在阿里云端做好之后,他会生成的。

#include "sht20.h"





#define SHT2X_ADDR             0x40

#define SHT2X_SOFTRESET        0xFE

#define SHT2X_MEAS_TEMPER      0xF3

#define SHT2X_MEAS_HUMIDITY    0xF5





int MainWindow::sht20_Init()

{



    fd=open(DEV_FILE,O_RDWR);



    if(fd<0)

    {

        printf("App:Open dev failed.\n");

        return -1;

//            goto END;

    }

    ioctl(fd, I2C_TENBIT, 0);

    ioctl(fd, I2C_SLAVE, SHT2X_ADDR);

    return fd;

}

void MainWindow::read_Sht20_data()

{

    char buf[50];

    static int now = 0;

    unsigned char tmp[5];

    unsigned short tempori,humiori;//温湿度原始数据



    static int temp_max=0,humi_max=0;

    int         ret = -1;



    ioctl(fd, I2C_SLAVE, SHT2X_ADDR);



    ret = sht2x_softreset(fd);

    if( ret < 0 )

    {

        printf("sht2x_softreset failure.\n");

//        return -2;

    }



    ret = sht2x_get_temper_rh(fd, &temp, &humi);

    if( ret < 0 )

    {

        printf("sht2x_get_temper_rh failure.\n");

//        return -3;

    }



        printf("SHT2x-T:%f RH:%f%%\n",temp,humi);



        ui->label_8->setText(QString::number(temp,'f',2));

        ui->label_9->setText(QString::number(humi,'f',2));





        if(show_temp_humi)

        {

            now_time++;

            dataCustomPlot->graph(0)->addData(now_time, temp);         //addData(double key, double value);原型

            dataCustomPlot->graph(1)->addData(now_time, humi);

            dataCustomPlot->replot();

        }



}

void MainWindow::msleep(unsigned int time)

{

    struct timespec sleeper, temp;

    sleeper.tv_sec = (time_t)(time/1000);

    sleeper.tv_nsec = (long)(time%1000)*1000000;

    nanosleep(&sleeper, &temp);



    return ;

}



int MainWindow::sht2x_softreset(int fd)

{

    int            ret = -1;

    uint8_t        buf[2] = {0};



    if( fd < 0 )

    {

        printf("input the invalid argument.\n");

        return -1;

    }



    buf[0] = SHT2X_SOFTRESET;

    ret = write(fd, buf, 1);

    if( ret < 0 )

    {

        printf("write softrest cmd to sht2x failure.\n");

        return -2;

    }

    msleep(50);



    return 0;

}



int MainWindow::sht2x_send_cmd_wr(int fd, char *which)

{

    int              ret = -1;

    uint8_t          buf[2] = {0};



    if( fd < 0 )

    {

        printf("input the invalid argument.\n");

        return -1;

    }



    if( strcmp(which, "temper") == 0 )

    {

        buf[0] = SHT2X_MEAS_TEMPER;

        ret = write(fd, buf, 1);

        if( ret < 0 )

        {

            printf("write temper cmd to sht2x failure.\n");

            return -2;

        }

        msleep(85);  //datasheet typ=66, max=85

    }

    else if( strcmp(which, "rh") == 0 )

    {

        buf[0] = SHT2X_MEAS_HUMIDITY;

        ret = write(fd, buf, 1);

        if( ret < 0 )

        {

            printf("write humidity cmd to sht2x failure.\n");

            return -3;

        }

        msleep(29);  //datasheet typ=22, max=29

    }



    return 0;

}



int MainWindow::sht2x_get_temper_rh(int fd, float *temper, float *rh)

{

    uint8_t              buf[4] = {0};

    int                  ret = -1;



    if( fd<0 || !temper || !rh )

    {

        printf("input the invalid arguments.\n");

        return -1;

    }



    ret = sht2x_send_cmd_wr(fd, "temper");

    if( ret < 0 )

    {

        printf("sht2x_send_cmd_wr temper failure.\n");

        return -2;

    }

    else

    {

        ret = read(fd, buf, 3);

        if( ret < 0 )

        {

            printf("get the temper failure.\n");

            return -3;

        }

        *temper = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;

    }



    ret = sht2x_send_cmd_wr(fd, "rh");

    if( ret < 0 )

    {

        printf("sht2x_send_cmd_wr rh failure.\n");

        return -2;

    }

    else

    {

        read(fd, buf, 3);

        if( ret < 0 )

        {

            printf("get the temper failure.\n");

            return -3;

        }

        *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;

    }



    return 0;

}

整体的sht20的温湿度代码,其实就是还是使用linux那套,操作linux底层,通过ioctl来操作,QT正好对这些都是可以兼容的。同理我们的SGP30也是可以这样的,直接读取。在树莓派上更多的一种是通过python进行编写测试,后期我们也可以自己尝试。

QSerialPort *myplotcom = new QSerialPort;

void MainWindow::usartDataInit()

{

//    UsartData::myplotcom = new QSerialPort;

    myplotcom->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections);//设置波特率和读写方向

    myplotcom->setDataBits(QSerialPort::Data8);      //数据位为8位

    myplotcom->setFlowControl(QSerialPort::NoFlowControl);//无流控制

    myplotcom->setParity(QSerialPort::NoParity); //无校验位

    myplotcom->setStopBits(QSerialPort::OneStop); //一位停止位

    #ifdef Q_OS_WIN//如果是windows系统

        myplotcom->setPortName("COM1");//ttymxc2

    #else//如果是unix或者其他系统

          myplotcom->setPortName("/dev/ttyAMA1");//ttymxc2

    #endif



    myplotcom ->open(QIODevice::ReadWrite);



    if(myplotcom->isOpen())

    {

        qDebug()<<"myplotcom is open"<<endl;

    }

    else

    {

        qDebug()<<"myplotcom is error"<<endl;

    }

//    connect(myplotcom,SIGNAL(readyRead()),this,SLOT(receiveInfo()));

    myReadTimer=new QTimer(this);

    myReadTimer->setInterval(500);

    connect(myReadTimer,&QTimer::timeout,this,&MainWindow::receiveInfo);//这个定时器是一进此界面就开始启动,定时读取,主要读取探测器参数。



    myReadTimer->start();

}

//接收到单片机发送的数据进行解析

void MainWindow::receiveInfo()

{





    if (myplotcom->bytesAvailable()<=0){return;}

    myHelper::Sleep(100);//延时100毫秒保证接收到的是一条完整的数据,而不是脱节的,

    QByteArray info = myplotcom->readAll();



    QString plotDataHex = myHelper::ByteArrayToHexStr(info);//分出16进制HEX文件打印输出,后期可以关闭

    qDebug() << plotDataHex << endl;



    if(info.length()<24)return;



    if((uchar)info.at(0)==0x32&&(uchar)info.at(1==0x3d))

    {

        PM_2_5_data = (uchar)info.at(6)<<8|(uchar)info.at(7);

        PM10_data = (uchar)info.at(8)<<8|(uchar)info.at(9);



        ui->label_12->setText(QString::number(PM_2_5_data));

        ui->label_13->setText(QString::number(PM10_data));

        if(show_pm2_5)

        {

            now_time++;

            dataCustomPlot->graph(0)->addData(now_time, PM_2_5_data);         //addData(double key, double value);原型

            dataCustomPlot->graph(1)->addData(now_time, PM10_data);



            dataCustomPlot->replot();

        }

    }



}

对于PM2.5来说我们的是通过一个串口,目前树莓派4可以做到了多串口,我使用了增加的一个串口,ttyAMA1这样就不用愁串口太少了。

void MainWindow::led_init()

{

    system("echo 26 > /sys/class/gpio/export");

    system("echo out > /sys/class/gpio/gpio26/direction");

    system("echo 0 > /sys/class/gpio/gpio26/value");



}



void MainWindow::on_pushButton_2_clicked()

{

    if(ui->pushButton_2->text() == "开灯")

    {

        on_off = true;

        system("echo 1 > /sys/class/gpio/gpio26/value");

        ui->pushButton_2->setText("关灯");

    }

    else

    {

        on_off = false;

        system("echo 0 > /sys/class/gpio/gpio26/value");

        ui->pushButton_2->setText("开灯");

    }

}

开关灯,同样的道理,使用linux底层操作就可以完成。

五、作品功能演示视频

【基于树莓派教育套件的物联网开发】

六、项目总结

首先还是感谢得捷电子提供此次物料费用,同时在得捷上也能购买相应的电子物料,到货也还是非常快的,其次本次大赛给的时间够长,完成了此次作品也学习了很多东西。最后树莓派用起来真的是生态丰富了,后续我再分享开发案例吧。

七、其他

SHT20.zip (5.44 KB, 下载次数: 2)

qt_opencv.zip (4.94 KB, 下载次数: 1)

基于树莓派教育套件的物联网开发.doc (703 KB, 下载次数: 5)

 

 

 

 

 

 

 

最新回复

非常好,内容很详细,图文并茂,学习了。!!!!!  详情 回复 发表于 2023-11-29 21:40
点赞 关注
 
 

回复
举报

6802

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

大家看后一定要下载楼主的基于树莓派教育套件的物联网开发.doc写的很好

 
 
 

回复

4908

帖子

12

TA的资源

版主

板凳
 

帮顶,楼主写得好(

 
 
 

回复

419

帖子

0

TA的资源

纯净的硅(中级)

4
 
非常好,内容很详细,图文并茂,学习了。!!!!!
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表