Renesa Version Board开发RT-Thread 之Client(WIFI)和上位机的数据传输

news2024/11/15 19:39:38

目录

概述

1 系统框架

1.1  模块介绍

1.1 Version-Board 开发板

1.1.1 Vision-Board简介

1.1.2 Vision-Board的资源

1.2 框架介绍

2 上位机App

2.1 UI设计

 2.2 代码实现

3 功能测试

3.1 网络连接

3.2 功能测试


概述

本文主要Renesa Version Board开发RT-Thread 之Client,使用C#语言开发一个上位机App实现Server功能。Renesa Version Board将Sensor数据(温度和湿度数据,环境光照数据, SR04 测量距离)通过WIFI上传给上位机。上位机将这些数据通过UI呈现出来。

1 系统框架

硬件实物图:

软件运行UI图:

1.1  模块介绍

1) 温湿度传感器: SHT20 采集环境温度和湿度数据

2)光照传感器: ISL2003S 采集环境光照数据

3)超声波测距传感器:SR04 测量距离

4) OLED 显示屏: 实时显示温度、湿度、光照和距离参数

关于这些模块的应用程序设计,参考如下文章: 

Renesa Version Board开发RT-Thread 之I2C驱动应用(ISL29035)_rt-thread i2c-CSDN博客

Renesa Version Board开发RT-Thread 之超声波测距模块(HC-SR04)-CSDN博客

Renesa Version Board开发RT-Thread 之I2C驱动应用(OLED)_rt-thread软件实现i2c-CSDN博客

Renesa Version Board开发RT-Thread 之I2C驱动应用(SHT20)-CSDN博客

1.1 Version-Board 开发板

1.1.1 Vision-Board简介

Vision-Board 开发板是 RT-Thread 推出基于瑞萨 Cortex-M85 架构 RA8D1 芯片,为工程师们提供了一个灵活、全面的开发平台,助力开发者在机器视觉领域获得更深层次的体验。

Vision Board搭载全球首颗 480 MHz Arm Cortex-M85芯片,该芯片拥有Helium和TrustZone技术的加持。官方提供的SDK包里集成了OpenMV机器视觉例程,配合MicroPython 解释器,使其可以流畅地开发机器视觉应用。

1.1.2 Vision-Board的资源

Vision-Board基于瑞萨R7FA8D1BH MCU设计,存储器:板卡搭载8M Bytes容量的Flash, 32M Bytes RAM。还支持摄像头接口,LCD接口。通信接口主要是WIFI。   

该板块自带DAP-LINK,无需外接调试器,使用一条USB线即可开发,这一点对于开发者非常友好。

其具体资源列表如下:

板卡正面资源信息:

板卡反面资源信息:

1.2 框架介绍

如下三个模块挂载到Renesa Version Board 的I2C接口上

1) 温湿度传感器

2)光照传感器

3) OLED 显示屏

IO通用接口:

SR04超声波测模块挂载到IO接口上,通过MCU内部的定时器和IO的 外部中断测出距离数据

 WIFI接口

Renesa Version Board  自带WIFI通信模块,这里只需使能该模块,然后建立Socket通信Client, 上位机实现Server功能。

Renesa Version Board  WIFI模块使用方法,可参考文章: 

Renesa Version Board开发RT-Thread 之WIFI创建Client-CSDN博客

2 上位机App

2.1 UI设计

上位机实现功能如下:

1) 上位机实现Server功能,Renesa Version Board 实现 Client功能,二者之间通过WIFI网络通信

2) 上位机实时显示Renesa Version Board 上传的Sensor数据,包括温度,湿度,光照,和距离

3)上位机可以配置小车的操作模块:手动模式/自动模式

4)在手动模式下,可以通过button控制小车的运行状态。

 上位机使用C#语言编写,其UI框架如下:

 2.2 代码实现

1) 使用C# WINFrom框架设计UI 

2)功能代码实现

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RT_ThreadApp
{
    public partial class MianWindows : Form
    {
        Socket sokWatch = null;         //负责监听 客户端段 连接请求的  套接字
        Thread threadWatch = null;      //负责 调用套接字, 执行 监听请求的线程

        ManualResetEvent allDone = new ManualResetEvent(false);
        Boolean b_watchCilent = false;   //使能监听
        Boolean b_connectSuccess = false;

        Boolean b_ClosingTCP = false;
        Boolean b_ListeningTCP = false;
        String uid = "RT_Thread";

        public MianWindows()
        {
            InitializeComponent();
        }

        private void MianWindows_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            var array = LOCALIpAddress.GetSpecifiedIpAddress(AddressFamily.InterNetwork);


            cbx_SerIP.Items.AddRange(array);
            if (cbx_SerIP.Items.Count >= 1)
            {
                cbx_SerIP.SelectedIndex = 0;
            }
            radioButton_manual.Checked = true;
        }

        private void btn_Connect_Click(object sender, EventArgs e)
        {
            //实例化 套接字 (ip4寻址协议,流式传输,TCP协议)
            sokWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //创建 ip对象
            IPAddress address = IPAddress.Parse(cbx_SerIP.Text.Trim());
            //创建网络节点对象 包含 ip和port
            IPEndPoint endpoint = new IPEndPoint(address, int.Parse(tbx_ServerPort.Text.Trim()));

            cbx_SerIP.Enabled = false;
            tbx_ServerPort.Enabled = false;

            try
            {
                //将 监听套接字  绑定到 对应的IP和端口
                sokWatch.Bind(endpoint);
                //设置 监听队列 长度为10(同时能够处理 10个连接请求)
                sokWatch.Listen(10);

                threadWatch = new Thread(StartWatch);
                threadWatch.IsBackground = true;
                threadWatch.Start();

                b_watchCilent = true;
                rtb_RecMonitor.AppendText("启动服务器成功......\r\n");
                btn_Connect.Enabled = false;
                btn_disConnect.Enabled = true;

                b_ListeningTCP = true;
                b_ClosingTCP = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 被线程调用 监听连接端口
        /// </summary>
        void StartWatch()
        {
            while (b_watchCilent)
            {
                try
                {
                    allDone.Reset();
                    sokWatch.BeginAccept(new AsyncCallback(AcceptCallback), sokWatch);
                    allDone.WaitOne();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        public Dictionary<string, StateObject> dictConnL = new Dictionary<string, StateObject>();
        public void AcceptCallback(IAsyncResult ar)
        {
            try
            {
                allDone.Set();
                Socket listener = (Socket)ar.AsyncState;
                Socket handler = listener.EndAccept(ar);
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                MonitorShowMsg(handler.RemoteEndPoint.ToString() + ":" + "连接成功", true);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        void MonitorShowMsg(string str, Boolean flag)
        {
            string dStr;

            DateTime day = DateTime.Now;

            dStr = "【" + day.Date.ToShortDateString() + "  " + day.ToLongTimeString() + "】" + "  " + str + "\r\n";

            if (flag)   //接受区监控
            {
                rtb_RecMonitor.Text += dStr;
            }
            else
            {
                rtb_RecMonitor.Text += dStr;
            }
        }

        public void ShowMsg(string msgStr)
        {
            rtb_RecMonitor.AppendText(msgStr + "\r\n");
        }


        public void EndAcceptCallBack(IAsyncResult ar)
        {
            threadWatch.Abort();
            Socket lenter = (Socket)ar.AsyncState;
            Socket handler = lenter.EndAccept(ar);
            handler.Dispose();
            lenter.Dispose();
            sokWatch.Dispose();
            sokWatch = null;
        }

        public void ReadCallback(IAsyncResult ar)
        {
            try
            {
                String content = String.Empty;
                StateObject state = (StateObject)ar.AsyncState;
                Socket handler = state.workSocket;
                int DataLength = handler.EndReceive(ar);
                byte[] TempBuff = new byte[DataLength];
                string str_recv = "";
                string[] str_Msg;

                Buffer.BlockCopy(state.buffer, 0, TempBuff, 0, TempBuff.Length);
                if (DataLength > 0)
                {
                    if (!dictConnL.ContainsKey(uid))
                    {
                        dictConnL.Add(uid, state);
                    }
                    else
                    {
                        dictConnL[uid] = state;
                    }

                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state);
                    // 显示log

                    String str = DateTime.Now.ToString();
                    str_recv = System.Text.Encoding.ASCII.GetString(state.buffer);
                    ShowMsg(str + " " + str_recv);

                    // 显示数据
                    str_Msg = str_recv.Split(',');
                    textBox_humidity.Text = str_Msg[0];
                    textBox_temp.Text = str_Msg[1];
                    textBox_lux.Text = str_Msg[2];
                    textBox_SR40.Text = str_Msg[3];

                    Console.WriteLine(str_Msg);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        private void send_wifi_Cmd(byte cmd )
        {
            byte mode = 0;
            byte[] cmdList = { cmd ,0};

            if (radioButton_manual.Checked)
            {
                mode = 0x02;
            }
            else if (radioButton_auto.Checked)
            {
                mode = 0x01;
            }

            cmdList[1] = mode;

            SendCmdBuf(dictConnL, uid, cmdList, cmdList.Length);
        }

        private void btn_disConnect_Click(object sender, EventArgs e)
        {
            cbx_SerIP.Enabled = true;
            tbx_ServerPort.Enabled = true;
            Net_Disconnect();
            dictConnL.Clear();
        }

        private void button_up_Click(object sender, EventArgs e)
        {
            byte cmd;

            cmd = 0x01;
            send_wifi_Cmd( cmd );
        }

        private void button_left_Click(object sender, EventArgs e)
        {
            byte cmd;

            cmd = 0x03;
            send_wifi_Cmd(cmd);
        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            byte cmd;

            cmd = 0x05;
            send_wifi_Cmd(cmd);
        }

        private void button_right_Click(object sender, EventArgs e)
        {
            byte cmd;

            cmd = 0x04;
            send_wifi_Cmd(cmd);
        }

        private void button_down_Click(object sender, EventArgs e)
        {
            byte cmd;

            cmd = 0x02;
            send_wifi_Cmd(cmd);
        }

        private void Net_Disconnect()
        {
            try
            {
                if (b_watchCilent)
                {
                    if (sokWatch != null)
                    {
                        b_ListeningTCP = false;
                        b_connectSuccess = false;
                        b_watchCilent = false;
                        btn_Connect.Enabled = true;
                        btn_disConnect.Enabled = false;
                        sokWatch.Dispose();
                        sokWatch.Close();
                        GC.Collect();

                        foreach (var v in dictConnL)
                        {
                            v.Value.workSocket.Close();
                        }
                    }
                }
                rtb_RecMonitor.Clear();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void SendCmdBuf(Dictionary<string, StateObject> dic, string UID, byte[] sendbyte, int length)
        {
            try
            {
                if (b_ListeningTCP)
                {
                    Send(dic[UID].workSocket, sendbyte, length);
                }
            }
            catch (Exception ex)  
            {
                Console.WriteLine(ex.Message);
            }
        }

        private void Send(Socket handler, byte[] data, int length)
        {
            try
            {
                if (b_ListeningTCP)
                    handler.BeginSend(data, 0, length, 0, new AsyncCallback(SendCallback), handler);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

            }
        }

        private void radioButton_auto_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton_auto.Enabled)
            {
                button_up.Enabled = false;
                button_down.Enabled = false;
                button_left.Enabled = false;
                button_right.Enabled = false;
                button_stop.Enabled = false;
                send_wifi_Cmd(0);
            }
        }

        private void radioButton_manual_CheckedChanged(object sender, EventArgs e)
        {
            button_up.Enabled = true;
            button_down.Enabled = true;
            button_left.Enabled = true;
            button_right.Enabled = true;
            button_stop.Enabled = true;
        }
    }

    public class LOCALIpAddress
    {
        /// <summary>
        /// 获取指定地址族的ip地址
        /// </summary>
        /// <param name="addressFamily"></param>
        /// <returns></returns>
        public static IPAddress[] GetSpecifiedIpAddress(AddressFamily addressFamily)
        {
            var addressList = GetIpAddresses();
            var ipv4Addresses = addressList.Where(x => x.AddressFamily == addressFamily).ToArray();
            return ipv4Addresses;
        }
        /// <summary>
        /// 获取本机的所有ip地址
        /// </summary>
        /// <returns></returns>
        public static IPAddress[] GetIpAddresses()
        {
            var hostName = Dns.GetHostName();
            var hostEntry = Dns.GetHostEntry(hostName);
            return hostEntry.AddressList;
        }
        /// <summary>
        /// 获取指定地址族的第一个ip地址
        /// </summary>
        /// <param name="addressFamily"></param>
        /// <returns></returns>
        public static IPAddress GetFirstSpecifiedIpAddress(AddressFamily addressFamily)
        {
            var addressList = GetIpAddresses();
            var ipv4Address = addressList.First(x => x.AddressFamily == addressFamily);
            return ipv4Address;
        }
    }

    public class StateObject
    {
        // Client socket.     
        public Socket workSocket = null;
        // Size of receive buffer.     
        public const int BufferSize = 1024 * 1024 * 5;
        // Receive buffer.     
        public byte[] buffer = new byte[BufferSize];
        // Received data string.     
        public StringBuilder sb = new StringBuilder();
    }
}

3 功能测试

3.1 网络连接

1)编译和运行上位机,点击监听按钮,等待Client连接

2)启动Version board下位机, 连接网络

 当出现如下信息,说明Version board  client已经连接上Server

3.2 功能测试

1)数据上传和UI展示

2)App发送控制命令给Version Board

测试项一: 选择手动模式后,控制按键不能操作

测试项二:

选择手动模式后,可通过发送控制命令给下位机, Version Board也能正确的接收到这些命令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2093229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MIX滤镜大师 v4.9.6.5 — 内置超过130款滤镜

MIX滤镜大师内置了超过 130 款高品质滤镜&#xff0c;涵盖多种照片风格&#xff0c;包括胶片时代的专业彩色反转片滤镜、自动识别人脸并磨皮增白的自拍滤镜、讲究线条和影调的单色滤镜以及追求夸张色彩的 LOMO 滤镜。此版本已解锁全部功能&#xff0c;去除广告&#xff0c;提供…

量化交易backtrader实践(四)_评价统计篇(4)_多个回测的评价列表

本节目标 在第1节里&#xff0c;我们认识了backtrader内置评价指标&#xff0c;了解了每个指标的大概内容&#xff1b;在第2节里把内置评价指标中比较常用的指标进行了获取和输出&#xff1b;第3节里我们探索其他backtrader中没有的评价指标&#xff0c;并对pyfolio, empyrica…

图形化编程系统学习10

项目需求&#xff1a; 点击绿旗&#xff0c;可以使用键盘控制小兔子在地图上移动&#xff0c;收集食物&#xff0c;但只能在黄色道路上移动。 食物碰到小兔子会变大后隐藏&#xff0c;并发出声音。 收集完所有食物&#xff0c;回到温暖的小窝 。 思路解析 1、添加背景和角色…

【书生大模型实战营】进阶岛 第1关 探索 InternLM 模型能力边界

文章目录 【书生大模型实战营】进阶岛 第1关 探索 InternLM 模型能力边界学习任务Bad Case 1&#xff1a;Bad Case 2&#xff1a;Bad Case 3&#xff1a;Bad Case 4&#xff1a;Bad Case 5&#xff1a;Good Case 1&#xff1a;Good Case 2&#xff1a;Good Case 3&#xff1a;G…

requests:一个强大的HTTP请求Python库

我是东哥&#xff0c;一个热衷于用Python简化日常工作的技术爱好者。今天&#xff0c;我要和大家分享一个网络请求的Python利器——requests库。你是否曾经在编写代码时&#xff0c;需要从网络上获取数据&#xff0c;却对复杂的HTTP协议感到头疼&#xff1f;requests库将帮你轻…

LMDeploy 量化部署进阶实践

1 配置LMDeploy环境 1.1 InternStudio开发机创建与环境搭建 打开InternStudio平台&#xff0c;进入如下界面并按箭头指示顺序点击创建开发机。 点选开发机&#xff0c;自拟一个开发机名称&#xff0c;选择Cuda12.2-conda镜像。 我们要运行参数量为7B的InternLM2.5&#xff0c;…

AI 内容创作:思考与实践

文章目录 LLM 与 RAGLLMRAGRAG 定制策略AI 写作助手演示 内容层次结构与内容深度优化有效的主题与段落结构内容深度的多样性与独特性提高文本逻辑性与连贯性模拟实践 内容评测与优化迭代机制内容评测自动迭代优化机制评估指标模拟实践 个性化写作与 AI 协同写作用户画像与需求分…

【C++ 第十八章】C++11 新增语法(3)

前情回顾&#xff1a; 【C11 新增语法&#xff08;1&#xff09;&#xff1a;1~6 点】 C11出现与历史、花括号统一初始化、initializer_list初始化列表、 auto、decltype、nullptr、STL的一些新变化 【C11 新增语法&#xff08;2&#xff09;&#xff1a;7~8 点】 右值引用和…

香橙派入手第一天

一、开箱 拿到快递回来以后&#xff0c;兴冲冲的把快递拆开&#xff0c;里面一共有一下几样东西&#xff0c;一个板卡&#xff0c;一个充电器&#xff0c;一个小风扇&#xff0c;还有一些安装用的零件和一把小螺丝刀。 值得一提的是这个充电器是最高支持65w的typec-typec的充电…

回溯法-0/1背包问题

什么是回溯法&#xff1f; 回溯法是一种搜索算法&#xff0c;它通过深度优先搜索的方式来解决决策问题。它从根节点开始&#xff0c;逐步扩展节点&#xff0c;直到找到所有可能的解。 回溯法的基本思想 开始节点&#xff1a;从根节点出发&#xff0c;这个节点是解空间的起点…

LLM 教程——如何为特定任务定制微调 BERT

通过本文&#xff0c;您将学会如何为特定的自然语言处理任务&#xff08;如分类、问答等&#xff09;微调BERT。 1、引言 BERT 是一个强大的预训练语言模型&#xff0c;可以用于多种下游任务&#xff0c;只需进行极小的修改。通过微调 BERT&#xff0c;您可以利用它的大规模知…

系统设计:一致性哈希的概念

目录 一、介绍 二、问题提出 三、朴素实施 四、一致性哈希 4.1 关闭服务器 4.2 添加新服务器 五、分布不均 5.1 虚拟节点 5.2 应用 六、结论 资源 一、介绍 我们生活在一个每天都会生成大量数据的世界里。在大公司中&#xff0c;几乎不可能将所有数据存储在单个服务器…

【区间dp、前缀和】 P1220 关路灯 题解

关路灯 题目描述 某一村庄在一条路线上安装了 n n n 盏路灯&#xff0c;每盏灯的功率有大有小&#xff08;即同一段时间内消耗的电量有多有少&#xff09;。老张就住在这条路中间某一路灯旁&#xff0c;他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯。 为了给村里…

APACHE NIFI—wait、notify组件报拒绝连接访问的报错

报错文字&#xff1a; Wait[idele44704-6fb6-1b60-ffff-ffffdcofbba2]Failed to process session due to Failed to get signal for c84c4aec-1287-4216-b1a2-f5c6fod4a3b7 due to java.net.ConnectException:Connection refused: org.apache.nifi.processor.exception.Proces…

jmeter响应断言、json断言、断言持续时间操作

一、响应断言 Apply to&#xff1a;断言应用的范围&#xff0c;这里默认&#xff0c;通常发出一个请求只触发一个服务器测试字段 响应文本&#xff0c;response响应体内的信息响应代码&#xff1a; 响应码&#xff0c;一般是200响应信息&#xff1a;响应码后面的返回的信息&am…

zdppy+vue3+onlyoffice文档管理系统实战 20240831上课笔记 继续完善登录功能

遗留的问题 1、整合验证码的接口2、渲染验证码3、实现验证码校验的功能4、验证码校验通过之后&#xff0c;再校验登录功能 验证码框架怎么使用 安装&#xff1a; pip install zdppy_captcha使用示例&#xff1a; import zdppy_api as api import zdppy_captcha import zdp…

Docker compose 安装 ELK

1. 简介 方案概述 我们使用 Filebeat 作为日志收集器&#xff0c;接入到 Redis 队列&#xff0c;然后消费队列中的日志数据流转到 Logstash 中进行解析处理&#xff0c;最后输出到 Elasticsearch 中&#xff0c;再由 Kibana 展示到页面上。我们采用 Elasticsearch 3 节点集群…

hello树先生——AVL树

AVL树 一.什么是AVL树二.AVL树的结构1.AVL树的节点结构2.插入函数3.旋转调整 三.平衡测试 一.什么是AVL树 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。…

【计组 | Cache原理】讲透Cache的所有概念与题型方法

Cache 写在前面&#xff1a;高速缓存Cache一直408中的重点以及绝对的难点&#xff0c;前几天我在复习计组第三章的知识&#xff0c;Cache这一节把我困住了&#xff0c;我发现很多概念我都不记得了&#xff0c;一些综合性强的计算题根本无从下手&#xff0c;我深知Cache对于每个…

1分钟把高质量AI知识库站点嵌入小程序

许多企业都有把 AI 知识库装进小程序、网站、企业微信、钉钉等的需求&#xff0c;让用户能够在小程序上访问到高品质的内容。奈何有太多限制&#xff0c;往往会遇到IP地址不被信任或技术对接接口配置等困难。HelpLook能帮你节省这些繁琐的程序&#xff0c;0代码快速将AI知识库站…