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

2024-09-01 01:04

本文主要是介绍Renesa Version Board开发RT-Thread 之Client(WIFI)和上位机的数据传输,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

概述

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和portIPEndPoint 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);// 显示logString 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也能正确的接收到这些命令

这篇关于Renesa Version Board开发RT-Thread 之Client(WIFI)和上位机的数据传输的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125508

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

全屋WiFi 7无死角! 华硕 RP-BE58无线信号放大器体验测评

《全屋WiFi7无死角!华硕RP-BE58无线信号放大器体验测评》家里网络总是有很多死角没有网,我决定入手一台支持Mesh组网的WiFi7路由系统以彻底解决网络覆盖问题,最终选择了一款功能非常... 自2023年WiFi 7技术标准(IEEE 802.11be)正式落地以来,这项第七代无线网络技术就以超高速