NI LabVIEW,CVI,数据采集等产品讨论区

取消
显示结果 
搜索替代 
您的意思是: 

蓝牙串口通信

已解决!
转到解答

大家好,

我现在要做一个从蓝牙读数据,然后做FFT处理。

蓝牙送过来的是Hex string,比如1FF,但是我的VI读数的时候会丢失数据,比如读到 1,1FF,1FF,FF,这样的数据。请问是怎么回事。

还有我希望能读到30秒的数据,然后送去做FFT,怎么样实现。

不好意思,刚接触Labview,大家多帮忙,谢谢

Baicy

0 项奖励
1 条消息(共 19 条)
8,521 次查看

你好,

 

造成串口数据丢失的原因有很多,比如硬件物理层链路的干扰、串口发送接收端串口参数配置不匹配等。

首先,可以用串口调试软件(这里)在PC端采用与LabVIEW相同的参数配置,验证一下硬件链路是否可靠,参数是否设置正确;

 

若测下来有问题,可考虑调整配置参数,改善串口连接线的抗干扰能力等方法解决。

若测下来一切OK,则考虑是否是程序的问题。

 

看到你程序中VISA Read的byte count设为50,不知道这样配置有什么原因吗?还有能否说明下蓝牙的数据格式是什么?这样有助于分析是否是程序造成了数据的丢失。

 

至于读30秒数据送去FFT的实现,个人认为可以使用FIFO Buffer。Buffer大小正好可以容纳30秒的数据。初始化的时候buffer清零。每次收到数据都添加到buffer中。每当数据添加后,即判断buffer是否满。如果是,则说明已经buffer中已经包含了当前时刻前30秒的采样点。这样即可使用buffer中的数据作为FFT的输入。由于是FIFO,用户不用考虑buffer溢出和删除过期数据的问题。

 

具体实现可以参考 Help>>Find Examples...>> Search "FIFO"的例子。

 

Good Luck~

0 项奖励
2 条消息(共 19 条)
8,510 次查看

 Charles.Tac

非常感谢你的回答。

我蓝牙设备是把10位的AD转换的数据发送到PC,用的是PIC单片机,然后发送的时候是00**,****,**** 四位,四位发送,所以最大值应该是hex 3FF,最小值000。

Labview我只了解一点点, VISA Read的byte count设为50是随便设的,因为我要采集30秒或者60秒(最好可调)的数据,然后发送做FFT。不知道您能否帮我?

 

我用hyper ternimal来做串口通信,得到的结果是想要的结果,请参照

http://forums.ni.com/t5/LabVIEW/serial-communication-with-bluetooth/m-p/1148870/highlight/false#M505...

然后我用example里面的advanced visa write and read.vi,结果也是想要的1FF,但是,我尝试调节Wait Until Next ms Multiple Function的输入时,数据就会丢失。

 

再次感谢!

Baicy

下载全部
0 项奖励
3 条消息(共 19 条)
8,495 次查看

发现问题是,每次我运行一次labview,程序不知道为什么随机从一个位开始读数。

比如,应该是1FF,1FF,1FF,但是读数的时候出来确实,1,FF,1FF,FF,或者1F,1FF,1FF,F,如下图所示,多按几次运行,出来的不同的结果。请问有人知道这个问题怎么解决吗?多谢!

16881iC3D1EE58012EFD77

0 项奖励
4 条消息(共 19 条)
8,489 次查看

你好,

 

请问当PC端程序运行时,蓝牙串口是否已经在发送数据?

如果是这样,那PC端程序一开始收到的第一个数据应该是不确定的。

如果蓝牙设备是在PC端程序运行后开始发送数据,可以试一下这样的scenario:

 

1. 运行程序,打开蓝牙设备串口,运行一段时间;

2. 停止程序运行(不关闭程序窗口);

3. 再次运行程序,并且不打开蓝牙设备串口;

 

如果此时程序还能接收到一些字符,则说明每次开始运行状态不一致可能是初始化没有清除receive buffer导致的。

这个问题可以通过VISA Flush I/O Buffer.vi 避免。 😉

 

0 项奖励
5 条消息(共 19 条)
8,453 次查看

谢谢,Charles.Tac

我使用了VISA Flush I/O Buffer.vi来初始化清除receive buffer。

我的蓝牙设备的确在连接的时候就发送数据,也就是说在运行labview前就可以在发送数据。

所以问题没有解决。我在想是不是可以让蓝牙发送一个判断数据,然后再接受。 labview 只有在接收到这个判断的数据后才开始接受处理数据。

我可以修改控制蓝牙的单片机来发送这个数据,请问用labview 怎么样实现这个判断。

我不知道这样是否可行,多谢赐教。

0 项奖励
6 条消息(共 19 条)
8,412 次查看

我们可以自定义通信的协议来保持Master/Slaver之间通信的同步,方法有很多,这里仅提供一些思路供参考:

 

1. 简单的通信协议,来避免收到无效数据。

   蓝牙设备(Slaver):初始化为[等待状态],接收PC端(Master)程序发送的串口数据;蓝牙设备接收到“开始发送命令”(某特定Byte or Bytes)后进入[数据发送状态],开始发送数据;在蓝牙设备在[数据发送状态]下轮询接收PC端的“停止发送命令”,一旦接收到该命令,进入[等待状态],停止数据发送。

   PC端程序(Master):初始化,发送“开始发送命令”,接收数据,发送“停止发送命令”,程序结束。

 

2. 如果你的应用实时性要求不高,可以在蓝牙设备发送数据中间隔一段时间插入一个标志位(该标志位需与数据有区别)这样PC端程序可以将该字符串之后的接收到的数据作为有效数据,而丢弃该字符串之前的数据。

   这种在数据中插入同步标志位的方法实现比较简单,PC端程序只需设置一标志位,并对接收到的每个数据加以判断,一旦发现同步标记,则将标志位置1,表示之后的数据位有效数据。

 

3. 前两种协议都比较简单。如果需要可靠地数据通信,可采用帧来发送数据,比如<CMD><DATA LEN><DATA><CRC 校验>,将若干个数据放在一帧中一起发送给PC。这样需要在蓝牙单片机和PC端LabVIEW程序上均实现帧的封装和解析函数,实现起来相比较之前两种方法复杂。

 

解决数据同步问题的方法有很多,可以权衡项目需求选择最适合的方法。 😉

 

0 项奖励
7 条消息(共 19 条)
8,356 次查看

谢谢,Charles.Tac,

我觉得第二个方案最简单。

蓝牙现在发送的数据格式是 00**,****,****,return.

所以我想检测到第一个return才开始接受数据,但是不知道怎么检测实现这个功能。可以用case,但是如何判断第一个return呢?

谢谢!

0 项奖励
8 条消息(共 19 条)
8,336 次查看

还有一个问题,我想要采集30秒的数据做fft,无论我怎么改循环的次数(300改到30000),显示的FFT的X轴从0-0.5,不是正确的频率读数。这又是什么原因?

谢谢

下载全部
0 项奖励
9 条消息(共 19 条)
8,327 次查看

你好,

 

对于第一个问题,我认为比较适用生产者消费者模型(这里)。将VISA串口数据接收预处理(生产者)和数据分析FFT(消费者)分别放在两个while循环中,并用队列、信号量等手段实现循环间数据交换。

 

需要说明的是,在生产者循环中,串口接收的数据最好进行一下预处理再加入队列,这样可以提高消费者处理数据的效率。预处理的方法就是按逗号将接收到的字符串划分,将划分后的字符串作为单元放入队列。此外,对于边缘情况,比如read buff末尾的字符串,需将其与下一次read开始位置的字符拼接成新字符串,存放到队列中。

 

对于return关键词的判断,可以放在消费者循环中。首先,我们需要一个标志位,可以在消费者循环上添加一个shift register来实现,将其初始化为False。其次,在消费者循环中放入一个case语句,当shift register为false,则每当从队列读取出一个单元,就将其与return比较一下,若不等则对shift register传回false,若相等则传回true。当shift register为true,则执行300次采样的for循环,循环中执行string to uint转换并将其放入数据队列中。最后,在true case中for循环之后,执行FFT等操作。

 

对于你第二个问题。令F为FFT转换得到的X轴归一化频率;f为信号频率;T为采样周期;fs为采样频率。则有F = f * T = f / fs,F是相对于采样频率的一种归一化频率[-1/2,1/2] 。实际上,对模拟信号的采样,是无限范围的实际频率变量f,向有限范围的离散频率变量F的映射。所以f = F * fs = F / T。

 

0 项奖励
10 条消息(共 19 条)
8,308 次查看