首页
室内基站 A3102P(单网口/POE供电)
- Details
- Written by: zhang
- Category: 产品
室内基站 A3102P
UWB 实时定位系统是采用UWB 无线通讯技术的TDOA 定位系统,定位精度30~50cm 左右。
A3102P 和A3106P 这两款基站都是吸顶式安装,通常用于室内。供电方式都是POE 供电。
基站可以配置为定位基站或时钟源。配置为基站时,负责接收标签发出的UWB定位信号,以及时钟源发出的时钟同步信号;配置为时钟源时,周期性发送时钟同步信号。最新版的固件允许基站硬件同时作为定位基站和时钟源。
A3102P 是单网口基站,通过网线连接到POE 交换机。
主要特性
1、 使用Qorvo DW3000芯片, 符合工信部对 UWB 频段的技术要求
2、 作为UWB 定位基站,接收标签发送的UWB 定位信号
3、 作为UWB 时钟源,定期发送时钟同步信号,使区域内的基站保持时钟一致
4、 使用POE 供电,不需要另外提供电源
5、 IP 地址可指定,或通过DHCP 自动分配
6、 定位引擎自动发现
7、 每个基站有符合EUI 规范的EUI64 ID
8、 时钟同步信号发送间隔可配置
9、 可配置PAN ID 过滤不相干的UWB 数据包
10、 最多可以与定位的5 个时钟源同步时钟
11、 可配置UWB 通讯数据包的前导码长度/PRF/PAC 等
12、 基站固件可升级
工牌标签 T1201C
- Details
- Written by: zhang
- Category: 产品
工牌标签 T1201C
我们量产的定位标签是工牌款式,使用DW1000作为UWB收发器。在前期使用DWM1000模块,后期使用自行设计的UWB模块,部分型号还增加了LNA/PA,以增加定位范围。
使用STM32F103RBT6作为主控MCU。这个芯片我们开始的采购价大约12元~14元左右,后来曾经涨到180元1片,真是太疯狂了,搞得我们很被动。不过,后来又跌回去了。
供电使用一片800mah的锂电作为电源,使用了一个USB接口充电,顺便作为标签配置接口。
标签上设计了一个MPU6050三维加速度计芯片,量产的时候,发现作用不是很大,后期在生产中就没贴这个芯片。
标签上设计了2个LED,一个红色一个绿色。
标签上设计了1个按钮,作为报警之类的用途。具体用途需要服务器端的设计。固件设计可以支持多个按钮,后来有OEM客户需要增加别的功能(如防拆等)。
如何从零开始实现TDOA技术的 UWB 精确定位系统(4)
- Details
- Written by: zhang
- Category: 技术
这是一个系列文章《如何从零开始实现TDOA技术的 UWB 精确定位系统》第4部分。
重要提示(劝退说明):
Q:做这个定位系统需要基础么?
A:文章不是写给小白看的,需要有电子技术和软件编程的基础
Q:你的这些硬件/软件是开源的吗?
A:不是开源的。这一系列文章是授人以“渔”,而不是授人以“鱼”。文章中我会介绍怎么实现UWB定位系统,告诉你如何克服难点,但不会直接把PCB的Gerber文件给你去做板子,不会把软件的源代码给你,不会把编译好的固件给你。我不会给你任何直接的结果,我只是告诉你方法。
Q:我个人对UWB定位很兴趣,可不可以做出一个定位系统?
A:如果是有很强的硬件/软件背景,并且有大量的时间,当然可以做得出来。文章就是写给你看的!
Q:我是商业公司,我想把UWB定位系统搞成一个商业产品。
A:当然可以。这文章也是写给你看的。如果你想自己从头构建整个系统,看了我的文章后,只需要画电路打板;构思软件结构再编码。就这样,所有的难点我都会在文中提到,并介绍了解决方法。你不需要招人来做算法研究。如果你想省事省时间,可以直接购买我们的电路图(AD工程文件),购买我们的软件源代码,然后快速进入生产环节。(网站: https://uwbhome.top)
标签的固件设计
之前的文章,我介绍了定位基站和标签的硬件设计、基站的固件设计(包括时钟同步的算法原理)。按正常的 roadmap,接下来应该是标签的固件设计。但是标签的固件实在是简单,没多少内容可写啊。想了想,还是为它写一篇吧。
标签最重要的功能是定期发送TDOA定位数据包,其他的功能都属于附加的。这个功能实现起来太简单了,decawave提供的样例代码中,很多都可以发送uwb数据包,只是数据包的格式需要符合我们的定义。
我们定义的 UWB TDOA定位数据包的格式是这样:
// Tag测距帧
// 广播帧, Tag 发出的测距消息, 各个 Anchor 根据收到这个帧的时间差来应用 TDOA 测距
typedef struct ieee154_broadcast_tag_range_frame {
uint8_t frameCtrl[2]; // 0, 2: frame control bytes 00-01: 0x01 (Frame Type 0x01=date), 0xC8 (0xC0=src extended address 64 bits, 0x08=dest address 16 bits)
uint8_t seq8; // 2, 1: sequence_number 02
uint8_t panID[2]; // 3, 2: PAN ID 03-04
uint8_t destAddr[2]; // 5, 2: 0xFFFF
uint8_t sourceAddr[8]; // 7, 8: 64Bits EUI地址
uint8_t messageType; // 15, 1: Message Type = RTLS_MSG_TYPE_TAG_RANGE
uint8_t seq64[8]; // 16, 8: Tag 发出的测距消息序号, 比 seq8 有更在的最大值
uint8_t powerVoltage[2]; // 24, 2: 电源电压*1000
uint8_t batteryVoltage[2]; // 26, 2: 电池电压*1000
uint8_t lighteness[2]; // 28, 2: 亮度, 直接 ADC 转换过来的值
uint8_t switchStatus; // 30, 1: 开关状态
int16_t imu_aacx; // 31, 2:
int16_t imu_aacy; // 33, 2:
int16_t imu_aacz; // 35, 2:
int32_t imu_roll; // 37, 4:
int32_t imu_pitch; // 41, 4:
int32_t imu_yaw; // 45, 4:
int16_t imu_temp; // 49, 2:
uint8_t fcs[2]; // 51, 2
} BROADCAST_TAG_RANGE_MESSAGE;
后来我们发现这个数据包太大了,有很多字段是没有必要的,所以换了一种小的格式:
// Tag测距帧, 最小测距帧
// 广播帧, Tag 发出的测距消息, 各个 Anchor 根据收到这个帧的时间差来应用 TDOA 测距
typedef struct ieee154_broadcast_tag_range_min_frame_v2 {
uint8_t frameCtrl[2]; // 0, 2: frame control bytes 00-01: 0x01 (Frame Type 0x01=date), 0xC8 (0xC0=src extended address 64 bits, 0x08=dest address 16 bits)
uint8_t seq8; // 2, 1: sequence_number 02
uint8_t panID[2]; // 3, 2: PAN ID 03-04
uint8_t destAddr[2]; // 5, 2: 0xFFFF
uint8_t sourceAddr[8]; // 7, 8: 64Bits EUI地址
uint8_t messageType; // 15, 1: Message Type = RTLS_MSG_TYPE_TAG_MIN_RANGE_V2
uint8_t seq32_3[3]; // 16, 3: Tag 发出的测距消息序号的高3字节, 与 seq8 组合为 seq32, 比 seq8 有更在的最大值
uint8_t switchStatus; // 19, 1: 开关状态
uint8_t fcs[2]; // 20, we allow space for the CRC as it is logically part of the message. However ScenSor TX calculates and adds these bytes.
} BROADCAST_TAG_RANGE_MIN_MESSAGE_V2; // 以上合计 22 字节
从53字节减小到22字节。这样,一个定位数据包在发送期间占用频率的时间减小了42%。这意味着可以容纳更多的标签。
你应该注意到,最小化的这个数据包中甚至没有包含电压数据,我们另外定义了一个包含电压数据的定位数据包,隔一段时间定期发送,因为电池电压不会快速变化,几分钟发一个带电压信息的包就可以了。
有客户定制了带心率传感器的标签,我们还增加了一个包含心率、血氧数据的定位数据包。
标签不像基站可以通过网络通讯,标签只能使用USB通讯。USB接口使用HID方式,可以免驱动。不要使用模拟COM口,因为如果使用COM通讯,一方面是需要安装驱动,另一方面是有可能会出现COM冲突,总之多出一些麻烦事。而使用HID方式则简单得多。
USB通讯需要使用外部晶振,不能使用STM32的内置RC振荡器。因为RC振荡器的频率不是很准确,如果使用RC振荡器,可能会导致兼容性问题,在一些电脑上因为频率不准而导致通讯失败。
STM32的省电模式使用 STOP 模式,这个模式比较适中。
要注意STM32的时钟频率。正常情况下,STM32的时钟是72MHz,因为我们不需要那么高的运算能力,所以使用48MHz就可以了,频率低一些可以省电。其他的更低频率不行,因为我们还需要给USB部分提供12MHz的频率,更低的频率组合不出12MHz。
还有就是,这么简单的程序不需要跑OS,直接裸奔就可以了。不跑OS还有两个原因:
- RTOS的结构复杂,我们还需要进行入STOP状态,这导致程序逻辑会复杂得多。
- STM32F103CBT6这个芯片的RAM/Flash都比较小,不适合太大的程序。
有什么想法,欢迎给我留言、评论。
这篇就这样吧,只差直接给出源代码了。下一篇开始介绍TDOA算法和定位引擎。
顺便做个找工作的广告。因为经营上的原因,公司散伙了。本人30+年工作经验,C/C++/Java/Delphi有20+年经验,Javascript/Python/Lua会一点。199x年x86汇编写过汉字系统,徒手Delphi写过邮件服务器,写过的应用系统无数,写过的代码应该超过200万行。10+年硬件设计经验,设计过多款嵌入式产品。这个UWB定位系统在初期,硬件软件都是我一个人弄出来的,产品成型之后才增加人手组团队。Base贵阳,或远程。如果有工作机会,请联系我要详细的简历。
如何从零开始实现TDOA技术的 UWB 精确定位系统(3)
- Details
- Written by: zhang
- Category: 技术
这是一个系列文章《如何从零开始实现TDOA技术的 UWB 精确定位系统》第3部分。
重要提示(劝退说明):
Q:做这个定位系统需要基础么?
A:文章不是写给小白看的,需要有电子技术和软件编程的基础
Q:你的这些硬件/软件是开源的吗?
A:不是开源的。这一系列文章是授人以“渔”,而不是授人以“鱼”。文章中我会介绍怎么实现UWB定位系统,告诉你如何克服难点,但不会直接把PCB的Gerber文件给你去做板子,不会把软件的源代码给你,不会把编译好的固件给你。我不会给你任何直接的结果,我只是告诉你方法。
Q:我个人对UWB定位很兴趣,可不可以做出一个定位系统?
A:如果是有很强的硬件/软件背景,并且有大量的时间,当然可以做得出来。文章就是写给你看的!
Q:我是商业公司,我想把UWB定位系统搞成一个商业产品。
A:当然可以。这文章也是写给你看的。如果你想自己从头构建整个系统,看了我的文章后,只需要画电路打板;构思软件结构再编码。就这样,所有的难点我都会在文中提到,并介绍了解决方法。你不需要招人来做算法研究。如果你想省事省时间,可以直接购买我们的电路图(AD工程文件),购买我们的软件源代码,然后快速进入生产环节。(网站: )
前一篇文章介绍了时钟同步的方法,是为了尽快拿点干货出来,免得读者觉得我只写一些泛泛而谈的大路货,没技术含量。下一步慢慢写吧。
基站固件设计-Flash布局
给MCU写固件的时候,如果是初学者,可能一上来直接就开始写应用程序了。老手都会先考虑布局,都要做些什么事,它们之间的关系是什么等等,要考虑周全。
基站的Flash分为4块:Bootloader、Application1、Application2、Data。
基站固件设计-在线升级
产品的固件可以现场升级很重要。现场升级是指不用把已经安装好的产品拆下,直接通过局域网之类的,在客户现场就可以升级固件。要知道,当产品已经安装在几千公里外的客户现场,突然发现固件中有个bug,你怎么办?如果能现场升级,在办公室把代码修正后,生成新固件,发给现场的客户,在现场升级固件。在这个过程中,你根本不需要离开你的办公室。
如果你的产品不能现场升级固件,对不起,发现bug后,只能请客户把产品拆下,寄回公司,你刷入新固件,再寄给客户......想起来都头大。
基站固件设计-Bootloader
Bootloader是启动代码,Application1/Application2是应用程序,Data放配置数据。
上电的时候,Bootloader中的程序先被执行,它判断Application1/Application2哪个有效,就跳转到有效的那个Application去执行。在Data区有两个变量: Application1Valid和Application2Valid,如果为True表示对应的Application有效。
在生产阶段,负责生产的工人只负责刷入Bootloader,这时,Application1Valid和Application2Valid都是False。
上电后,如果找不到有效的Application,Bootloader会启动网络部分的代码: DHCP Client/TCP Client/DNS Client/UDP Server/UDP Client等。如果它连接在网络,会一直在网络中发出一个UDP包,请求初始化。
出厂初始化程序收到请求初始化的UDP包后,会登记新基站的基本信息,如MCU ID等,然后给它分配一个 EUI64 的地址,这个地址以后就是这个基站的ID了。还会分配一个系列号。然后还要写入缺省的配置数据。出厂初始化程序接下来开始发送固件给新基站。Bootloader收到固件后,写入到一个无效的Application区(刚开始,Application1区肯定是无效的)。固件会被分很多个包发送。固件接收完成后,Bootloader会置Applicaiton1Valid为True,然后重启。
再次上电后,Bootloader发现Application1有效,就跳转到Application1去执行。
这就完成了新固件的启动。
其实,Bootloader中的网络相关代码和固件接收代码,只在出厂初始化的时候执行一次,以后就不会再被执行到。因为在出厂之后,Applicaiton1和Application2总有一个是有效的。
如果Bootloader发现两个区都有效,会把第二个区置为无效。只允许一个区有效,无效的那个区用保留给新的升级固件使用。
基站固件设计-固件升级
在固件的Application中,也有类似前述Bootloader的固件升级代码。只是它要判断哪个区无效,把收到的新固件保存到无效的那个区,并置对应的变量为有效,把正在运行的这个区对应的变量置为无效。下次上电时,Bootloader就会跳转到新固件去执行。
基站固件设计-程序结构
现在介绍Application怎么写。
因为基站的功能还是有点多,好几个功能需要“并发”执行。这里的“并发”是指逻辑上的,因为STM32不支持抢先式执行/不支持多线程/只有一个核,所有代码都只能顺序执行,并不会有真正的并发。
所以,MCU不能裸奔,得使用RTOS。当初,因为比较熟悉uCOS,所以就用它了。如果是现在选择,大概率会用FreeRTOS。
- 时钟同步部分,如果作为时钟源,需要定期发送UWB时钟同步包;
- UWB芯片处理,负责DW1000的状态管理,以及UWB数据包的收发。
- 网络处理,包括DHCP Client/DNS Client/UDP Server/UDP Client等。
- 看门狗任务
先从简单的部分开始介绍。
看门狗任务
STM32有看门狗,如果不及时调用喂狗函数,MCU就会认为程序挂了,它会自动复位。我们的程序分为很多个任务,每一个任务都有挂掉的可能,所以,我们搞一个看门狗任务。每个任务有一个看门狗变量,由各个任务及时把它置0,看门狗任务循环给这些变量加1,并判断这些变量的值,如果超过某个界限,就判断对应的任务挂了,就复位MCU。看门狗任务还负责喂狗。
总之,我们要保证各个任务都能正常工作,当任务挂掉后,立即复位。
DW1000处理任务
考虑到将来可能会在一个基站内置多个DW1000,所以我们把DW1000相关数据定义为一个结构:
这样的话,有些代码就可以复用了,程序处理起来会灵活一些。
在这里要吐槽一下DecaWave,DW1000的工作情况并不很稳定。有时会出现一些奇怪的现象。所以,我们还要经常判断DW1000状态,如果不在期望的状态,判定死了,我们要及时对DW1000进行复位。当然,这种情况并不太多,但是只要有,我们就得处理。否则在客户现场,基站活着、固件活着,但是DW1000死了,无法收发数据,就很尴尬了。
基站的主要工作就是接收UWB数据包,为了保证收到的数据包能及时处理,不影响后续的UWB包的接收,我们搞了一个队列来做缓存。DW1000任务只管收UWB包,收到后立即放入队列,然后又处理后续的UWB包。队列中的包由其他任务来处理。
网络任务
网络任务的工作比较杂乱。
它最重要的一个工作就是把收到的UWB重新组装成一个新的数据包,发给定位引擎。
其它的工作就是辅助性的了。
DHCP客户端。很多时候,IP地址的管理很麻烦,如果每个基站都一一配置IP地址,是一件比较辛苦的事。一般来说,除非客户要求每台设置都要配置指定的IP地址,否则使用DHCP来分配IP地址是比较方便的。W5500芯片有DHCP客户的代码例子,直接复制过来改改就可以了。它的代码在处理上不太完整,DHCP的IP地址合约到期后的续签,还有如果有IP地址冲突怎么处理等等,我们对代码做了一些完善工作。
DNS客户端。其实可以不用的。如果定位引擎不在局域网内,而是在很远的地方,例如Internet上的云主机。使用DNS指定定位引擎的地址会好一些,万一定位引擎的IP地址变了,但是域名可以不变。我们没有使用DNS,之前的客户基本都在局域网内,把定位引擎放在Internet上的只有为数不多的几个。
UDP。我们使用UDP来实现定位引擎自动发现。如果配置为定位引擎自动发现,网络任务会检查是否与定位引擎建立起TCP连接,如果没有,它会广播一个UDP包(定位引擎发现包),要求定位引擎给回复。定位引擎收到UDP包后,会回复自己的IP地址之类的信息。基站就会与定位引擎建立起TCP连接。
基站配置。在早期的版本中,我们使用UDP来传送基站配置信息。使用UDP的好处是可以广播,缺点是UDP是无连接的,有丢失的可能。后来我们统一改成使用TCP来传送基站配置信息。基站配置程序先通过UDP广播,查找局域网内都有哪些基站,然后与它们建立TCP连接,双向传送配置信息。
基站固件设计-杂项功能
恢复出厂设置。为了保证数据安全,基站设置有密码,基站配置程序必须使用正确的用户名和密码才能对基站进行配置。既然是密码,就有忘记的可能。另外也有可能用户配置基站,把数据弄乱了,自己懒得一个一个的改,所以我们设计了一个恢复出厂设置功能。
USART1_TX和USART1_RX在出厂的产品上没用,对应的是PA9和PA10被挪用于检测是否恢复出厂设置。需要恢复出厂设置时,把这两个引脚之一与GND短接,重新上电就可以了。
报警功能。有个客户打算把我们的系统用在煤矿(重要提醒,产品需要本安认证才用在煤矿),需要增加一个报警功能。当发生险情时,系统可以发报警信息给标签,让携带标签的工人可以得时得到撤离信号。流程大致是这样,应用程序调用定位引擎的接口,定位引擎通过网络把数据包发给时钟源(或扮演时钟名的基站),时钟源在发送时钟同步数据包的任务中发出UWB报警数据包,标签收到UWB报警数据包后,立即报警(红灯,或震动)。报警消息有两种:广播给所有人,指定ID的标签。
基站固件设计-可能会遇到的坑
第一个坑是DW1000的状态。前面已经说过了。我们在系统中要定期检查DW1000的工作状态,如果不正常,要及时对DW1000进行复位。
第二坑是W5500的晶振。我们第一次量产基站时,W5500使用的是无源晶振,这是很正常的电路设计,我们之前的测试板都是这样设计的。我们在之前的一些产品中用到W5500也是使用无源晶振。但是基站生产完成,收到货后测试发现有很多基站的W5500的晶振不起振。当时想了各种办法来找原因,换pad电容,重新焊接等等。这个起振问题,似乎处于一个不确定状态,有些上电一段时间会自己起来,有些就总是不起振,有些甚至开始起振了后面会自己停。以至于我们只好在固件初始化的时候判断W5500的状态,看它状态正常不,还在网络任务中经常性的判断W5500的状态。后来我们的硬件设计改用有源晶振,就一切OK了。再之后,我们其他用到W5500的产品中,都使用有源晶振。
这是基站固件设计的第二篇文章,以后再回头修改修改充实一些细节吧。
顺便做个找工作的广告。因为经营上的原因,公司散伙了。本人30+年工作经验,顺手的语言C/C++/Java/Delphi,这个UWB定位系统在初期硬件软件都是我一个人弄出来的,产品成型之后才增加人手组团队。Base贵阳,或远程。如果有工作机会,请联系我要详细的简历。
Page 5 of 10