前言

上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件!


目录

一、整体思路

二、效果提前展示

2-1、软件部分展示

2-2、硬件部分展示

三、基于C#的客户端软件说明

  3-1、整体框架介绍:

  3-2、部分技术细节介绍

   3-2-1、串口操作

   3-2-2、JiSuan函数说明及核心算法介绍

四、阶段小结

五、相关链接


一、整体思路

>_<" 如下图,利用我们上三节开发的超声波发射与接收设备构成一个:2固定接收头+1可移动超声波发射头的平面定位硬件设备。由上一节我们知道:在一个采样周期内硬件定位装置完成2次测距,即图中的x和y的长度。又因为我们双接收模块部分两个接收头的距离是固定的L,所以我们可以根据数学公式求出移动头的具体坐标,然后在PC上进行仿真。

二、效果提前展示

2-1、软件部分展示:

>_<" 模式一:用来动态获取下位机测得x和y数据经过几何运算将硬件结构映射到FORM窗口中,实现动态仿真。这里:COM3处表示接收模块所连接的串口为COM3;右边的四个数据分别表示所测实时的x,y的长度,以及串口缓冲区的有效数据剩余q(用栈来实现),和所有采集到的有效点转换为FORM中坐标点的队列大小(用队列来实现)。

>_<" 模式二:每次获得新的有效点时连接上一次的点和这一次的点形成活动端的移动路径展示效果。(这里由于从原始数据到FORM上坐标转换时放大了7倍,所以波动比较大,其实精度是在1cm左右波动的。

2-2、硬件部分展示:

>_<" 1个发送头(即可移动头)+2个接收头[在这节中要把两个接收头并排固定间距为14cm,即L的长度]

 

>_<" 超声波发送模块集成电路+超声波接收模块集成电路

 

>_<" 硬件整体图(注意这里再次强调接收头要并排固定相距14cm!嘿嘿,由于晚上写的,俺的手机又太渣,30万像素Java机,也称“学霸机”,就不能把最新的固定好的图发给大家看了!)

三、基于C#的客户端软件说明

3-1、整体框架介绍:

>_<" 如下图:上位机程序构成很简单,初始化函数DrawHS()进行获得当前可用串口、实例化并挂起用于数据处理的线程、启动定时器用于周期性刷新屏幕。①当用户选中超声波接收模块所对应的串口并成功连接后,原始数据的到来会触发串口数据接收函数执行来接收数据,这里接收来的数据保存在Q的栈里;②然后JiSuan线程会提取栈内的最新数据进行处理,并把得出的有效转化为FORM平面的点放入P的点集队列里;③定时器的定时刷新周期到来会根据上面的计算来重绘当前界面。这里模式一和模式二按钮决定采用Draw1()函数还是Draw2()函数进行绘图。

3-2、部分技术细节介绍

3-2-1、串口操作

>_<" 首先,你得在FORM中加入一个ComboBox,命名为PortList,即:下拉COM口选择框。

>_<" 其次,你得有个SerialPort控件,命名为serialPort1,即:C#提供的串口对象。

>_<" 那么,在初始化函数中写入如下代码获得当前可用串口并加入ComboBox中,注意最后一句:表示如果有可用串口,默认选择第一个。

 //Get all port list for selection
//获得所有的端口列表,并显示在列表内
PortList.Items.Clear();
string[] Ports = SerialPort.GetPortNames();
for (int i = ; i < Ports.Length; i++)
{
string s = Ports[i].ToUpper();
Regex reg = new Regex("[^COM\\d]", RegexOptions.IgnoreCase | RegexOptions.Multiline);//正则表达式
s = reg.Replace(s, "");
PortList.Items.Add(s);
}
if (Ports.Length > ) PortList.SelectedIndex = ;

>_<" 接下来,对于串口的连接就比较简单了。如本工程,当你从ComboBox中选择一个串口时,然后点击连接按钮进行连接,那么连接按钮就是负责串口连接功能:这里根据连接按钮的状态判断当前连接情况,当有连接时,点击连接按钮表示断开连接;当没有连接时,点击连接按钮,则会连接从ComboBox中选中的串口。这里要注意(20行):由于串口数据接收属于触发事件,有数据到缓冲区才会触发并接收数据,这里实例化一个串口数据接收句柄就是负责响应触发接收数据的函数,即:PortDataReceived~

 SerialPort Connection = new SerialPort();
private void 链接ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (链接ToolStripMenuItem.Text == "关闭")//通过控件名字判断当前状态
{
Connection.Close();
链接ToolStripMenuItem.Text = "链接";//改变控件名字
PortList.Enabled = true;
JS.Suspend();//挂起线程
}
else
{
if (!Connection.IsOpen)
{
JS.Resume();//继续已挂起的线程
Connection = new SerialPort();
Connection.PortName = PortList.SelectedItem.ToString();
Connection.Open();
Connection.ReadTimeout = ;
Connection.DataReceived += new SerialDataReceivedEventHandler(PortDataReceived);
链接ToolStripMenuItem.Text = "关闭";
PortList.Enabled = false;
}
}
}

>_<" 如上面介绍,每当串口有数据传来就会触发该函数执行来接收串口缓冲区数据。这里的第6行即是从串口缓冲区读取length长的数据放入data数组中,0表示放入data[0]开始。下面8、9两行即把原始数据压入栈给JiSuan线程处理。

 private byte[] data;//接收的数据数组
private int length = ;//一次从缓冲区取出数据长度
private void PortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
data = new byte[length];
if (Connection.Read(data, , length) != length) return;
Connection.DiscardInBuffer();
Connection.DiscardOutBuffer();
Q.Push(data[]);//压入栈
Q.Push(data[]);
}

3-2-2、JiSuan函数说明及核心算法介绍

>_<" 如下图,原始数据转换为FORM坐标系下移动端的坐标(x,y)的求法:首先利用三角函数根据原始数据计算出a,b的值,然后根据一定比例放大a,b值再根据坐标关系求出FORM坐标系下的移动点(x,y)的坐标。

>_<" 当理解上述计算转换过程,下面的代码便不难理解。这个JiSuan的函数其实是个数据处理的线程,一直处于while循环下,当栈Q中存在待处理原始数据时,则取出原始数据,判断原始数据是否正确合理,如果合理则分别找出data_x和data_y的值,即原始值(这里,由于下位机发送过来data_x和data_y的顺序先后不定,于是在下位机中将data_y的数据取相反数发送过来,所以在这里能够巧妙地区分)。接下来就是采用上述所述方法进行计算移动点的FORM坐标系下的坐标了。这里的Show字符串是为了保存最初您看到的显示的x:23 y:21 q:0 p:123信息。

 private string Show="";
private void JiSuan()
{
while (true)
{
if (Q.Count()<) continue;
data[] = Q.Pop();
data[] = Q.Pop();
//从串口读原始数据并判断是否合法
//这里串口的数据位发送到x、y接收头的距离,并且只保留1m内的距离
//为了分辨清晰,把y的真实距离取相反数经串口发送
//当上位机串口收到2个距离放到data[2]中,当负的强制转换为int类型时要用225-接收的数据才能转化为原数
int data_x = , data_y = ;
if ((int)data[] >= && (int)data[] <= )
{
data_y = - data[];
data_x = data[];
}
else if ((int)data[] <= && (int)data[] >= )
{
data_x = data[];
data_y = - data[];
}
else continue;
//下面是根据收到的发射到两个接收头的距离计算相应的平面坐标位置
//a,b为原始偏移,x,y为坐标平面的对应点坐标
double cos8 = (14.0 * 14.0 + data_x * data_x * 1.0 - data_y * data_y * 1.0) / (2.0 * 14.0 * data_x);
double a = 1.0 * data_x * Math.Sin(Math.Acos(cos8));
double b = 1.0 * data_x * cos8;
x = ((int)( * a));
y = ((int)( * b)) + ;
if (x < ) continue;
p3.X = x;
p3.Y = y;
P.Add(p3);
rect.X = x - ;
rect.Y = y - ;
//用于显示收到数据
Show = "x:";
Show += data_x;
Show += " y:";
Show += data_y;
Show += " q:";
Show += Q.Count();
Show += " p:";
Show += P.Count();
canShow = true;//可以显示
}
}

四、阶段小结

>_<" 经过这四小节的学习,从最初的想法到如今的实现,收获颇丰!对于模拟电路有了更深刻的认识,对于51单片机的应用有个进一步的提高,对于PC上位机的开发也有了新的了解和体会。可以说,硬件的难在于其变化性,即使是绝美的方案也会出现真实世界莫名因素的影响,让你头大;软件的难在于逻辑之难,本项目虽小,但是用了多线程的思维,里面隐隐涉及到线程同步和死锁的问题,只是有些错误在调试阶段已经被淘汰,大家在这个最终的方案下也就无法想象原初的各种死锁、运行时中断、迟缓等问题了。此外,可能是前三篇过于偏向于硬件,所以大家可能不会理睬,但是如果您真的对该篇文章感兴趣的话,还是建议您仔细阅读下前三篇的介绍,毕竟这个过程中硬件几乎占了大半个江山呢~其实,本来的想法是:第一阶段把这个做成个平面定位的类似于电子白板的触控模块,第二阶段把这个做成三接收头的空间三维定位装置,结合当前体感游戏、手势识别等开发出更有意义的产品,但是在研究的过程中发现超声波定位其本身存在不可忽视的缺点,容易反射相互干扰等,接下来的想法造成了本质性的阻碍。由于最近学业较忙,所以这个超声波的研究就暂且为止!最后,感谢大家的支持!

五、相关链接 

[自娱自乐] 1、超声波测距模块DIY笔记(一)链接:http://www.cnblogs.com/zjutlitao/p/4014855.html

[自娱自乐] 2、超声波测距模块DIY笔记(二)链接:http://www.cnblogs.com/zjutlitao/p/4029937.html

[自娱自乐] 3、超声波测距模块DIY笔记(三)链接:http://www.cnblogs.com/zjutlitao/p/4069272.html

[源码]该项目C#工程VS2012平台:http://pan.baidu.com/s/1ntqkxNb

[源码]该项目超声波接收模块51单片机代码(和第三篇的不同):http://pan.baidu.com/s/1jGA9vqI

[打击盗版]请进入博主主页查看原版博文:http://www.cnblogs.com/zjutlitao/

[自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发的更多相关文章

  1. [自娱自乐] 3、超声波测距模块DIY笔记(三)

    前言 上一节我们已经研究了超声波接收模块并自己设计了一个超声波接收模块,在此基础上又尝试用单片机加反相器构成生成40KHz的超声波发射电路,可是发现采用这种设计的发射电路存在严重的发射功率太低问题,对 ...

  2. [自娱自乐] 2、超声波测距模块DIY笔记(二)

    前言 上一节我们已经大致浏览下目前销售的超声波测距模块同时设计了自己的分析电路,这次由于我买的电子元件都到了,所以就动手实验了下!至写该笔记时已经设计出超声波接收模块和超声波发射模块,同时存在超声波发 ...

  3. STM32—驱动HC-SR04超声波测距模块

    文章目录 超声波测距原理 HC-SR04工作原理 STM32实现驱动 1.引脚的配置 2.时序控制 3.时间差测量 4.如何将距离测出来 超声波测距原理 利用HC-SR04超声波测距模块可以实现比较精 ...

  4. loto示波器实践——超声波测距模块

    我们这里用到的超声波测距模块,一般是用于arduino智能小车自动避障的.经常见到的应用是使用单片机或者stm32和这种模块结合进行开发的. 我们使用LOTO示波器可以更直观和快速的看到超声波测量距离 ...

  5. 张高兴的 Windows 10 IoT 开发笔记:HC-SR04 超声波测距模块

    HC-SR04 采用 IO 触发测距.下面介绍一下其在 Windows 10 IoT Core 环境下的用法. 项目运行在 Raspberry Pi 2/3 上,使用 C# 进行编码. 1. 准备 H ...

  6. 基于STM32F103ZET6 HC_SR04超声波测距模块

    这是最后的实验现象,改变不同的角度即可测得距离 板子 PZ6806L 超声波模块 HC_SR04 HC_SR04模块讲解 通过该超声波模块说明书,可明白供电需VCC 5V  还需GND  ECHO(回 ...

  7. 树莓派 HC-SRO4超声波测距模块的使用

    先上个图 这个模块的针脚跟之前玩的那三个有所区别,除了VCC和GND两个针脚,还多了两个Trig和Echo针脚,分别是输出和输入,Trig我接的是20针脚,Echo是21 该模块的工作原理为,先向TR ...

  8. Arduino 控制超声波测距模块

    一.实物图 二.例子代码 用到数字2 和3 引脚,还有两个就是vcc GND两个阴脚,用模块连线比较简单

  9. KS103超声波测距模块

    max232:电平转换芯片,将电脑的RS-232标准串口(高+12V,低-12V)转换为(高+5V,低0V). 电脑串口(RS -232) => 单片机串口(TTL串口) SIPEX SP323 ...

随机推荐

  1. Hibernate之jpa实体映射的三种继承关系

    在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class).Joined策略(table per subclass)和Table_PER_Class策略. 1.单表继承 ...

  2. Continue To DO!

    (1)Valid Anagram 解题思路: 使用一个数组,首先遍历S相应位置加1,然后遍历T,判断此时如果相应位置为零返回FALSE,否则就减一.T遍历完毕后返回true. 代码如下: public ...

  3. The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决

    问题 The certificate used to sign "AppName" has either expired or has been revoked. An updat ...

  4. return exit _exit

    (1)进程终止: C程序的终止分为两种:正常终止和异常终止. 正常终止分为: return, exit, _exit, _Exit, pthreade_exit. 异常中指分为: abort, SIG ...

  5. css 层的嵌套

    html <div class="menu"> <ul> <li><a class="li1" title=" ...

  6. Hibernate 根据实体名称得到DB表名以及表对应的Sequence name

    DB: oracle 10g; entityName:com.signaldemand.flank.hibernate.model.实体名 1. 根据实体名获取DB表相对应的表名 Class<? ...

  7. 第一章 JacksonUtil 序列化与反序列化属性总结

    1.json-lib与Jackson 关于json-lib与Jackson对比总结如下: 1).性能方面,Jackson的处理能力高出Json-lib10倍左右. 2).json-lib已经停止更新, ...

  8. ubuntu14安装java8

    http://ubuntuhandbook.org/index.php/2015/01/install-openjdk-8-ubuntu-14-04-12-04-lts/

  9. Adding AirDrop File Sharing Feature to Your iOS Apps

    http://www.appcoda.com/ios7-airdrop-programming-tutorial/ Adding AirDrop File Sharing Feature to You ...

  10. oracle 干掉连接

    最初由 lutheran 发布 [B]进程超出最大连接数,数据库不能连接,查看v$session里只有80多个会话,但是在v$process里有350个数据库进程,数据库使用的是专用服务器,有大部分的 ...