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

目录

概述

[1 系统框架](#1 系统框架)

[1.1 模块介绍](#1.1 模块介绍)

[1.1 Version-Board 开发板](#1.1 Version-Board 开发板)

[1.1.1 Vision-Board简介](#1.1.1 Vision-Board简介)

[1.1.2 Vision-Board的资源](#1.1.2 Vision-Board的资源)

[1.2 框架介绍](#1.2 框架介绍)

[2 上位机App](#2 上位机App)

[2.1 UI设计](#2.1 UI设计)

[2.2 代码实现](#2.2 代码实现)

[3 功能测试](#3 功能测试)

[3.1 网络连接](#3.1 网络连接)

[3.2 功能测试](#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)功能代码实现

cs 复制代码
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也能正确的接收到这些命令

相关推荐
DREAM依旧8 分钟前
隐马尔科夫模型|前向算法|Viterbi 算法
人工智能
GocNeverGiveUp21 分钟前
机器学习2-NumPy
人工智能·机器学习·numpy
B站计算机毕业设计超人1 小时前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
学术头条1 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
18号房客1 小时前
一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理·sklearn
feifeikon1 小时前
机器学习DAY3 : 线性回归与最小二乘法与sklearn实现 (线性回归完)
人工智能·机器学习·线性回归
游客5202 小时前
opencv中的常用的100个API
图像处理·人工智能·python·opencv·计算机视觉
古希腊掌管学习的神2 小时前
[机器学习]sklearn入门指南(2)
人工智能·机器学习·sklearn
凡人的AI工具箱2 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
咸鱼桨2 小时前
《庐山派从入门到...》PWM板载蜂鸣器
人工智能·windows·python·k230·庐山派