admin 管理员组

文章数量: 887021

补充项

  • pps来的时候,utc还没有来,但逻辑上pps来晶振触发器就会触发维持毫秒定时器,当utc来的时候才可以获取整数秒,这理论上就会出现一段时间里没有整数秒只有小数秒的imu时间戳,针对此种情况,如果是采集数据后再后处理,可以直接删除这段数据;如果是实时系统,使用状态判断,初始化 rmc同步 pps同步,最后在imu时间戳。

前言

时间同步是组合导航里不得不解决的问题,为什么要做时间同步,用我自己的理解来说就是:不做时间同步,那就是用从前的A传感器信息来校正当前的B传感器信息,两者都不是描述的同一个时间点的物体,融合出来的结果能对才是见了鬼了。
(ps:以工程经验来说,其实不少人做法是:以gps10hz,imu100hz,低速车载环境为例,在程序端取一个gps数据再取10个imu数据,这样其实也可以粗糙的使用)
具体原理可以查看新手入门系列4——MEMS IMU原始数据采集和时间同步的那些坑,本文中只做具体的工程应用,就是为了让读者能够快速手搓板子实现时间同步,然后把精力放在组合导航算法研究上。

硬件平台

STM32F407ZGT6+um982(gps设备)+mti300(imu设备)+stlink(下载器)
GPS设备需要能够输出PPS脉冲触发,1s一次;IMU需要设置成触发模式

软件平台

win10+STM32cubeIDE+micro-lab(串口调试助手,这玩意挺好用的)

最终效果

原理

时间同步准确的说是同步采样。在GPS和imu中就是用GPS时间来uimu数据打上时间戳,但由于数据从串口来是需要耗时,且解算也需要耗时,以我使用的这款gps设备为例子:配置好后串口输出为:

$KSXT,20190909084745.00,116.23662400,40.07897925,68.3830,299.22,67.03,190.28,0.022,,1,3,46,28,,,,-0.004,-0.021,-0.020,,*27

其中"20190909084745.00"为utc时间(yyyymmddhhmmss.ss),但GPS频率为10hz,imu为高频(以100hz为例),只用utc时间的话是没法给imu打上时间戳的,且utc小数位后时间还要考虑各种延迟,并不准确。最好的方法就是利用utc的整数秒,和stm32定时器来维持一个小数秒。拼接成一个完整得时间戳来给imu打上。
这里要有个概念,对于PPS的,其得益于卫星的授时功能,精度很高,至于为啥这么高,俺不懂,就是误差在纳秒级,以它为基准就很准就成了。那我们写代码的思路就来了:
1.PPS第一次来,因为其快于串口传输来的UTC时间,那PPS第一次来后,记录下稍晚来的utc时间整数秒作为IMU时间戳的整数秒(这可以从下面博客中上电瞬间串口5来的数据来看,明显先PPS来了启动了定时器,然后后续含有UTC时间的GPS数据才来,整数秒有数据是因为缓存区存有以前的整数秒数据,会在第一次来UTC时间后被更新成最新的)

2.第一次PPS来的时候开启晶振定时器,让晶振计数器开始计数,并翻转触发口的电平,形成一个20ms一次的上升沿脉冲。
这里的定时时间设置为0.01s.怎么设置涉及到STM32定时器,后续会介绍到,参照这个链接里的公式

为了后续扩展u盘存储功能,我这里主频设置为48Mhz,即我想设置定时器为0.01s。则在stm32cubeide中我的定时器两个参数分别为47999和9

3、除了第一次PPS脉冲来,那后面每次PPS来都表示距离第一次运行了一整秒了,则 T 整数 + 1 秒 T_{\text{整数}}+1\text{秒} T整数+1

注意:这里有个需要注意的逻辑是:PPS信号可能会丢失,那下一次PPS来则就不能单纯+1s,需要检测最后一次整数秒+1与当前获取到的串口utc时间差距是否在1s内,如果在1s内,说明PPS中途没有丢失,不是,则 T 整数 = u t c 时间当前整数秒 T_{\text{整数}}=utc_{\text{时间当前整数秒}} T整数=utc时间当前整数秒


4.从第二次开始,PPS来一次需要重置一次定时器,小数秒ss001重置为0,防止长时间运行晶振定时器误差累积,用PPS来校正
5.
t i m u 时间戳 = T 整数秒 + s s 001 ∗ 0.01 t_{imu\text{时间戳}}=T_{\text{整数秒}}+ss001*0.01 timu时间戳=T整数秒+ss0010.01
6.最后都是通过串口5发射出去,为了防止同时来GPS数据和IMU数据时候串口被一个占用,另一个无法发射出去,使用了串口DMA的环形缓存区设计。注意TX RX都设置成normal模式,这里我翻了跟头,设置成circle,导致数据循环发送,一个数据发几遍
7.最后IMU触发口波形

8.还有很多改进空间,比如增加U盘存储功能,比如弄成多线程,比如我这里还出现一个问题,比如是10hz的GPS,50hz的IMU,那时间戳在运行过程中,虽然可以准确保证一个GPS和5个imu数据一段一段的来,但时间戳上我不知道为啥会出现诸如这样子的情况,会突变,

这也是我把这套系统开源的原因,难度不是很大,我很久没碰过单片机,然后stm32cubeide也是现学的,不少东西没考虑周全,但用来同步采样数据是没啥大的问题,也希望佬们能分享改进后的源码,不甚感激,能因为我这篇博客解决你组合导航上一点点小问题,甚是荣幸。

一步步手把手的复现我的板子和采集系统

下载好stm32cubeide 1.30.0(没测试过其他版本,这里提供一个1.30.0版本的百度云链接)
确保没有中文路径安装也没有中文的项目名字
1.新建项目

2.选择自己芯片,我用的是一块140多元的stm32f407zgt6,淘宝链接

3.next后给定英文项目名

4.

5.按序号来

6.按照序号来,打开后这样

6.要一份自己所用单片机的电路原理图,这个小系统用到的各个口子和序号如下:

当然还有为了检测用的GPIO口和蜂鸣器,这部分比较简单,具体可以看我放出的代码


具体引脚、时钟树、代码生成配置

这部分主要说明怎么用刚建立好的新项目里配置新文件。要是用我得同款板子直接使用我的项目就成,这里写一下是为了让读者能够适配自己的板子,能够尽快的部署自己的时间同步系统。
1.基础配置——先不管要干啥,按照我的图配置,后面再解释配置了啥子,毕竟我们的目标是尽快实现时间同步然后精力放在其他地方
a)仿真器选择(这里我使用的stlink)

b)

c)gpio口设置
这里分两种,一种是led0-2和BEED直接gpio_output和Imutriger,另一种是用来接收PPS的中断,具体来说就是


上述几个都是GPIO_Output类型,具体名字是使用了右击修改的。
然后PPS信号由于是要由GPS引入,这里的gpio使用中断,注意开中断

d)串口设置
这里使用了3个串口——串口1和2用来接收gps和imu数据,串口5用来发送处理后数据


串口2和5同样配置,注意一个点是这里DMA模式都选择normal

e)配置时钟树和定时器——注意这里的48Mhz就成,其他的按照我的图来,使用外部晶振


为了配置成0.01s一次计数,

至于为啥这么配置,可以看这个教程
注意配置

到这里基本配置完成。生成代码即可


保存即可生成代码

2.功能说明(简述代码大概逻辑)
2.1 上电检测
这部分逻辑很简单,就是调用了蜂鸣器和3个led灯,原理图如下:

上电后依次闪烁LED0-2,然后蜂鸣器响一声代表检测板子完成

  Check_LED();//板子依次亮起,闪烁,最后保持全亮
  Check_BEED();//蜂鸣器响一声,代表计时器启动

2.2串口数据获取
正常获取数据即可
2.3数据拼接
这里使用了DMA环形缓冲区,把gps来的数据和imu数据都放到缓冲区内,防止gps和imu同时来数据只能发送其中一个
完整工程代码我到了博客主页资源里,自行下载就成,我都是设置的免费开源。可以任意下载。

杂谈

1.当然,该板子在实测过程中出现了跳秒现象,可惜我确实没有时间弄了,很多杂事缠身,我给提供给了导师做本科毕设题目之一,有时候真的挺无力的。想快点工作了,攒点小钱钱。
2.不少博客下面我都留下了自己联系方式,继续留一下,qq3233456044,有关博客的任何东西细节都欢迎一起交流。

本文标签: 时间 基础