您的位置:首页 > 新闻 > 资讯 > Renesa Version Board开发RT-Thread 之Client(WIFI)和上位机的数据传输

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

2024/10/16 16:19:42 来源:https://blog.csdn.net/mftang/article/details/141759509  浏览:    关键词: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也能正确的接收到这些命令

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com