本文主要是介绍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)和上位机的数据传输的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!