物联网智能农场项目的嵌入式开发

项目的github地址:https://github.com/zhangruyi3906/smartFarm/

总结:

第一天实训总体十分的轻松

每天坚持写技术日志

认真写好工程实践报告

智能农场模拟演示视频

M0开发板的控制命令的格式:

环境:十六进制 36字节 BB ID 24 00 命令格式: 十六进制 —- 36个字节

DD  id 24 00  00 --- 开灯
DD  id 24 00  01 --- 关灯
DD  id 24 00  02 -- 开蜂鸣器
DD  id 24 00  03 -- 关蜂鸣器
DD  id 24 00  04 --- 开风扇
DD  id 24 00  08 --- 关风扇

eg:dd 09 24 00 01

linux基础

常用命令

1、打开终端:

  1. 双击图标

  2. ctrl alt + t

2、创建文件夹

  1. mkdir 文件名

dpkg -l 查看所有已经安装的软件

dpkg -s vim 查看某一个软件的安装状态

cd 直接进入的就是家目录=/home/zhangruyi

根目录下是共享的,公有的文件,普通用户没有操作权限

sudo apt-get remove vim

sudo apt-get install vim

在线从某一个网站上下载软件包到本地

3、进入文件夹

  1. cd 文件名

  2. cd .. 返回上一级目录

4、查询当前目录文件

  1. ls

5、vi编辑器

  1. 命令行模式

    1. yy 复制一行

    2. dd 删除/剪切

    3. p 粘贴

    4. u 撤销

    5. xyy 复制多行

    6. xdd 删除多行

  2. 插入模式

    1. a i o 进入插入模式

  3. 底行模式(退出插入模式 ESC)

    1. :w 保存

    2. :q 退出

    3. :wq 保存并退出

6、gcc 编译器

  1. gcc test.c //默认生成a.out可执行文件

  2. gcc test.c -o test //生成test可执行文件

ps -ef | grep nginxps aux | grep nginx 都可以用来查看包含 "nginx" 关键词的进程信息,只是显示的格式略有不同。

ps -efps aux 都是用于查看系统中的进程信息的命令。

  • | 是管道符号,用于将前一个命令的输出作为后一个命令的输入。

  • grep nginx 用于过滤出包含 "nginx" 关键词的进程信息。

  • 所用指令:

    touch 1.c

    ls

    gcc 1.c

    vi 1.c

    ./a.out 执行二进制文件

    a9开发板

    IMG_20240607_111715(1)

    m0开发板

    IMG_20240607_111706

    zigbee模块:

    IMG_20240607_111709

    智能农场

    1. 需求:温湿度、光照、浴霸、排风扇、报警、自动浇水、摄像头

    2. 怎么来实现?

    19d9834caf66116c94d331e1a1d442a2

    总结:

    要用到的技术

    1. 编程语言:C语言、C++

    2. 开发平台:linux系统、QT

    3. v4l2编程(摄像头采集图像)

    4. zigbee编程

    5. 网络编程

    最终实现效果图

    image-20240605213805603

    系统架构图:

    3ffc500a3b850cfa463895956d00dbae

    Zigbee协调器节点(建立网络,配对和终端节点连接)和终端节点(接收数据,从温湿度传感器等接收数据)

    打开USB0串口,调用函数进行串口属性初始化

    创建camera_fd套接字

    一个qt客户端的代码文件,主要是qt的ui界面及其公共按钮监听,就是按下后发送命令,

    三个系统:虚拟机、本机windows和能够烧录Linux系统的A9开发板,本机负责安装和启动QT客户端,虚拟机负责将运行在开发板上的服务器端代码.c文件进行编译为可执行文件默认为a.out,也可以改名字,再将可执行文件通过scp命令传给开发板执行,而后开发板通过串口连接的zigbee模块,与控制电路(智能农场)交互信息,控制电路(也就是风扇、小灯的那块板子m0)的代码是提前写好烧制的,中间可以用串口调试助手来预调试。

    最后是win上的QT客户端—–网线局域网——-》linux服务器主板(arm-cortexA9)—>(串口线)—-> zigbee协调器+摄像头–>(m0上的zigbee终端)+M0(stm32类型的)

    服务器主板:1.电源线 2.超级终端控制线 3. 串口线(摄像头+zigbee协调器)4.网线(局域网+通过ssh协议安全接收传输过来的文件)

    透传数据

    电阻R、电容C、串口线、SD卡烧录镜像8GB、zigbee

    大小端: pc-小端 网络字节序:大端

    tcp/ip中的大小端是什么

    在计算机中,大小端(Endianness)是指数据在内存中的存储方式。具体来说,大小端描述了多字节数据在内存中的字节顺序。

    小端(Little Endian)是指数据的低位字节存储在内存的低地址处,而高位字节存储在内存的高地址处。这意味着在小端系统中,较低有效位的字节会先存储在内存中。

    大端(Big Endian)则相反,是指数据的高位字节存储在内存的低地址处,而低位字节存储在内存的高地址处。在大端系统中,较高有效位的字节会先存储在内存中。

    在网络通信中,TCP/IP协议规定了网络字节序(Network Byte Order),即数据在网络中传输的字节顺序。TCP/IP协议要求使用大端字节序进行数据传输,也就是说,数据在网络中传输时,高位字节先传输,低位字节后传输。

    为了在不同大小端系统之间进行数据传输,通常需要进行字节序转换。在C语言中,可以使用函数如htons和htonl将主机字节序转换为网络字节序,使用函数如ntohs和ntohl将网络字节序转换为主机字节序。

    (在大端系统中,高位字节存储在低地址,低位字节存储在高地址;而在小端系统中,高位字节存储在高地址,低位字节存储在低地址。)

    · ping命令:测试网络连通性 导致ping不通的原因: 1)双方不在同网段 2)防火墙拦截

    涉及的参与方

    (1)客户端(Qt上位机)

    (2)服务端 + 摄像头 处理数据及中间通道

    中间桥梁 串口(传输数据)、zigbee网络

    (3)设备端:M0采集数据(实现相应的功能)

    网络编程

    文件描述符 : 文件的唯一标识

    套接字

    1. TCP 传输控制协议、有连接、保证数据可靠性;

    2. 两种模型

      1. b/s (b 浏览器 s 服务器)

      2. c/s (c 客户端 s 服务器)

    ip:用来区分主机的唯一标识;

    端口号:用来判断主机接收到的数据,应该交给那个任务去处理

    TCP服务器的搭建流程:

    1. 创建套接字 socket()

    2. 绑定ip、端口号 bind()

    3. 监听连接 listen()

    4. 建立连接 accept()

    5. 通信 read()/write()

    6. 关闭套接字 close()

    socket()

    功能:创建套接字

    头文件:
        #include <sys/types.h>          /* See NOTES */
        #include <sys/socket.h>
    ​
    函数原型:
        int socket(int domain, int type, int protocol);
    参数:
        domain:
            AF_INET    ipv4的协议 
        type:
            SOCK_STREAM 流式套接字
        protocol:
        传0,使用默认协议
    返回值:
         成功:返回新创建的套接字
         失败:返回-1
    ​
       
      返回0代表程序执行成功
      返回-1代表程序执行失败
    eg:
        int sockfd = socket(AF_INET,SOCK_STREAM,0);
        if(sockfd == -1)
        {
            perror("socket");
            return -1;
        }
    ​
    缩进命令:gg = G

    bind()

    功能:绑定ip、端口号

    头文件:
        #include <sys/types.h>          /* See NOTES */
        #include <sys/socket.h>
    ​
    函数原型:
        int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    ​
    参数:
        sockfd:
             创建的套接字
        addr:
             地址结构体
        addrlen:
             地址结构体的长度
    返回值:
         成功:返回0
         失败:返回-1
                 
    //通用地址结构体             
    struct sockaddr {
        sa_family_t sa_family;
        char        sa_data[14];
    }
    //ipv4地址结构体
    struct sockaddr_in {
        sa_family_t    sin_family; /* address family: AF_INET */
        in_port_t      sin_port;   /* port in network byte order */
        struct in_addr sin_addr;   /* internet address */
    };
    ​
    /* Internet address. */
    struct in_addr {
        uint32_t       s_addr;     /* address in network byte order */
    };
    ​
    ​
    eg:
        struct sockaddr_in saddr;
        bzreo(&saddr,sizeof(saddr));
    ​
        saddr.sin_family = AF_INET;
        saddr.sin_port   = htons(6666);
        saddr.sin_addr.s_addr = inet_addr("192.168.6.33");
    ​
        if(-1 == bind(sockfd, (struct sockaddr *)&saddr,sizeof(saddr)))
        {
            perror("bind");
            return -1;
        }
    ​

    listen()

    eg:
    ​
     if(-1 == listen(sockfd, 5))
     {
         perror("listen");
         return -1;
     }
    ​
    ​

    accept()

    eg:
       int connfd = accept(sockfd, NULL, NULL);
        if(connfd == -1)
        {
            perror("connfd");
            return -1;
        }
    ​
    read()/write();
    close(connfd);
    close(sockfd);

    tcp/ip协议通信示意图

    https://i3.wp.com/img-blog.csdnimg.cn/57129c6b6dc0410797aa2560bfb080c9.png#pic_center

    cf0368a96ea8a837114d447d12e9be0d

    image-20240605210243370

    华清张路东老师—–网络通信相关

    1. 下述命令找不到

    d333c42082284d6cc15b442acb7e3d1a

    使用:sudo apt-get install lib32z1

    #

    *【ARM】arm-linux-gcc 没有那个文件或目录*

    【ARM】arm-linux-gcc 没有那个文件或目录_linux 怎么找到arm-linux-gcc存放的路径-CSDN博客【ARM】arm-linux-gcc 没有那个文件或目录_linux 怎么找到arm-linux-gcc存放的路径-CSDN博客v100pc_search_result_base4&utm_term=zhangruyi%40zhangruyi-virtual-machine%3A%7E%2Fgcc-4.6.4%2Fbin%24%20arm-linux-gcc%20-v%20bash%3A%20%2Fhome%2Fzhangruyi%2Fgcc-4.6.4%2Fbin%2Farm-linux-gcc%3A%20No%20such%20file%20or%20directory%20zhangruyi%40zhang&spm=1018.2226.3001.4187

    由以下问题所引发的上述问题:

    img

    img

    1. 虚拟机连外网ping命令,和tracecert命令都是检查网络的可达性和网络情况的,基于icmp网络报文控制协议。

    2. 实验设备

      869ae8b4a2da36c48515107e276f7e67

    3. 105b72307d94aedfbf023ae890983db9

      需要安装一个dll文件

      image-20240605210038457

    (1)XShell的使用文档,

    连接服务器如虚拟机Linux,

    串口配置

    img

    弹出下面对话框

    img

    选本地有的串口,波特率选115200

    img

    虚拟机配置

    img

    img

    img

    (2)windows版本的Qt安装方法

    1、 先断网(wifi和有限网络都断开)

    2、 点击安装包

    img

    3、 一直点击下一步,直到下面的页面

    img

    4、选择MinGW 5.10.1 32bit

    img

    5、继续安装直到完成。

    (3)网络编程相关知识

    1.网络编程: 0.地址结构: 1.IP地址: typedef uint32_t in_addr_in;

            struct in_addr {
                in_addr_in s_addr;
            };
            
            #include <sys/socket.h>
            #include <netinet/in.h>
            #include <arpa/inet.h>
            #include <netinet/ip.h>
    ​
            将字符型ip转成整型ip: in_addr_t inet_addr(const char *cp)
            将整型ip转成字符型ip: char *inet_ntoa(struct in_addr in);
            使用任意IP:htonl(INADDR_ANY);
        2.通用地址结构:
            struct sockaddr {
                u_short sa_family;
                char sa_data[14];
            };
        
        3.Internet协议地址结构:
            struct sockaddr_in {
                u_short sin_family;         //地址族  AF_INET
                u_short sin_port;       //端口号,4位,0~65535,0~1023被系统占用,普通应用程序用1024以上端口,如8080,8888等等,赋值htons(8080)或者htons(8080)
                struct in_addr sin_addr;    //IPV4地址,服务器地址,inet_addr(const char *cp)
                char sin_zero[8];       //字节的补充
            };

    ​ 1.创建服务器: ​ 0.套接字: ​ 文件描述符–>唯一标识一个打开或者创建的文件 ​ PID –>唯一标识一个进程 ​ 套接字–>标识一个服务器/客户端(特殊的文件描述符) ​ ​ IP: IP地址 ​ 端口:标识发到哪个进程 ​ 1.创建套接字: #include <sys/types.h> #include <sys/socket.h> /* See NOTES */

            函数原型:   int socket(int domain, int type, int protocol);
            函数功能:   创建套接字 
            参数:         domain  -- AF_INET
                        type    -- SOCK_STREAM
                        protocol-- 0
            返回值:    成功:套接字
                        失败:-1

    ​ 2.绑定服务器IP、端口等:{ ​ #include <sys/types.h> ​ #include <sys/socket.h> /* See NOTES */ ​ ​ 函数原型: int bind(int sockfd, const struct sockaddr *addr, int addrlen) ​ 函数功能: 绑定服务器IP、端口 ​ 参数: sockfd — 套接字 ​ addr — 地址结构(通用地址结构) ​ addrlen– 地址结构的长度 ​ 返回值: 成功0 失败-1 }

        3.设置监听数:{
            #include <sys/types.h>
            #include <sys/socket.h>         /* See NOTES */
    ​
            函数原型:   int listen(int sockfd, int backlog);
            函数功能:   设置监听数
            参数:     sockfd  -- 套接字
                        backlog -- 最大等待队列长度
                
            返回值:    成功返回0,失败返回-1
        }
        
        4.等待连接:{
            #include <sys/types.h>
            #include <sys/socket.h>     /* See NOTES */
            
            函数原型:   int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
            函数功能:   等待连接
            参数:     sockfd -- 监听套接字
                        addr   -- 客户端的地址结构
                        addrlen-- 客户端地址结构长度
            
            返回值:    成功返回客户端读写套接字,失败返回-1
        }
        
        5.通信:
            收: read:
            #include <unistd.h>
    ​
            函数原型:   ssize_t read (int fd, void *buf, size_t count);
            函数功能:   读
            参数:     fd   --打开的文件的文件描述符
                        buf  --从fd中读,存放到buf中
                        count--读多少字节
    ​
            返回值:    成功返回实际读到的字节数,返回0代表读到文件末尾,失败返回-1

    ​ 发:write: ​ #include <unistd.h> ​ ​ 函数原型: ssize_t write(int fd, const void *buf, size_t count); ​ 函数功能: 写 ​ 参数: ​ fd –写入的文件的文件描述符 ​ buf –从哪里写 ​ count–写多少字节 ​ 返回值: 成功返回实际写入的字节数,返回0代表读完了,失败返回-1

    ​ 6. 关闭:{ ​ #include <unistd.h> ​ ​ 函数原型: int close(int fd) ​ 函数功能: 关闭 ​ 参数: fd — 打开的文件的文件描述符 ​ 返回值: 成功返回0,失败返回-1 ​ } ​ } ​ 2.创建客户端: ​ 1.创建套接字: ​ #include <sys/types.h> ​ #include <sys/socket.h> /* See NOTES */ ​ 函数原型: int socket(int domain, int type, int protocol); 函数功能: 创建套接字 参数: domain — AF_INET type — SocK_STREAM protocol–0 返回值: 成功:套接字 失败:-1

    ​ 2.连接服务器IP、端口等: ​ # include <sys/types.h > ​ # include <sys/socket.h > ​ ​ 函数原型: int connect(int sockfd, struct sockaddr *addr, int addrlen); ​ 函数功能: 连接服务器IP、端口等 ​ 参数: sockfd — 套接字 ​ addr — 服务端的地址结构(通用地址结构) ​ addrlen — 地址结构的长度 ​ 返回值: 成功0 失败-1

        3.通信:
            收: read:
            #include <unistd.h>
    ​
            函数原型:   ssize_t read (int fd, void *buf, size_t count);
            函数功能:   读
            参数:     fd   --打开的文件的文件描述符
                        buf  --从fd中读,存放到buf中
                        count--读多少字节
    ​
            返回值:    成功返回实际读到的字节数,返回0代表读到文件末尾,失败返回-1

    ​ 发:write: ​ #include <unistd.h> ​ ​ 函数原型: ssize_t write(int fd, const void *buf, size_t count); ​ 函数功能: 写 ​ 参数: ​ fd –写入的文件的文件描述符 ​ buf –从哪里写 ​ count–写多少字节 ​ 返回值: 成功返回实际写入的字节数,返回0代表读完了,失败返回-1

    ​ 4. 关闭:{ ​ #include <unistd.h> ​ ​ 函数原型: int close(int fd) ​ 函数功能: 关闭 ​ 参数: fd — 打开的文件的文件描述符 ​ 返回值: 成功返回0,失败返回-1 ​ } ​ }

    作者:m0_63267586

    物联沃分享整理
    物联沃-IOTWORD物联网 » 物联网智能农场项目的嵌入式开发

    发表回复