我将如何让小型振荡器以精确的 31,891,269,116 µHz 运行?

电器工程 Arduino 计时器
2022-01-06 15:33:56

我正在寻找为 Arduino 构建一个在火星时间运行的 RTC 模块。转换因子是 1.0274912510 地球秒到 1 火星秒。

虽然我已经设法在连接到常规 RTC 模块的 Arduino Uno 上使用定点数学以 <2 秒的分辨率(这并不完全理想,我更喜欢 300 毫秒的精度)以编程方式完成此任务,但我是想知道是否有可能让某种低压振荡器以精确的 31,891,269,116 µHz (31.891269116 kHz) 运行,它或多或少可以与标准的 32 kHz 时钟晶体互换(但是,我愿意接受其他想法,所以只要它们不是过于昂贵。)

任何想法这怎么可能?或者,也可以接受某种每 1.0274912510 秒关闭一次的计时器。

4个回答

你可以比 Brian Drummond 的建议做得更好。尽管您的振荡器确实是系统中最大的误差源,但如果很容易不添加额外的系统误差,则没有理由添加额外的系统误差。

将定时器间隔设置为 33668 滴答,从 0 开始计数器,在每次定时器中断时,将计数器增加 6754。

如果在递增后,计数器 >= 8105,则减去 8105,并将下一秒的计时器间隔设置为 33669 滴答。

否则,不理会计数器并将下一秒的定时器间隔设置为 33668。

这会给你(假设一个完美的 32.768kHz 晶体)平均间隔

(33668 + 6754 / 8105) / 32768 ~= 1.0274912510006

秒(相对于 1.0274912510 小于万亿分之一的误差),而不是 1.0274963378906 秒(几乎百万分之 5 的误差)。这意味着时钟的长期精度将真正取决于振荡器的精度;数学造成的误差每年的误差将大大少于一个刻度。尽管任何一秒的长度都会产生高达 25ppm 的相对误差,但在越来越长的平均时间间隔内,误差就会消失。

这是Bresenham 算法应用于计时,发现分数 6754/8105 如下:

32768 * 1.027491251 = 33668.833312768

33668.833312768 的精确连分数是 [33668; 1、4、1、1349、1、7]。

去掉最后一项得到近似值 33668 + 6754 / 8105,它的所有部分都整齐地适合 16 位。

像其他人一样使用 32768kHz 晶振,但除以 33669,得到 -5.08ppm 误差。(如果您愿意,可以通过调整负载电容来消除它)。

这并不精确,但对于火星时钟来说,它会和任何地球石英钟一样好。也就是说,忽略火星环境温度的温度补偿问题,大多数手表晶体只能切割给地球使用,除非你能找到火星供应商......

我会使用 MSP430 中的计数器定时器外设进行除法,并且(假设您正在驱动标准石英机械时钟机芯)每秒在其输出引脚上生成双极 30ms 脉冲,大致遵循您可以的原始时序在示波器上测量。

Arduino 或类似产品可以完成这项工作,但 MSP 可以在脉冲之间进入睡眠状态,在 LF 振荡器运行时消耗低于 1uA。这是一个带有手表源代码和 PCB 的示例设计- 到目前为止只有地球时间,尽管这可能可以通过更改常数来修复。

精确运行在31,891,269,116 µhz 的振荡器或周期为 1.0274912510 秒的计时器将需要至少 \$10^{-10}\$ 的精度。最好的办法是使用精确到 \$10^{-14}\$的原子钟。

它可以用一个 10MHz 的铷或其他原子参考时钟来完成,也许是一个 PLL 来提供(比如说)100MHz,然后用一个 ~36 位相位累加器进行计数,以提供 0.001Hz 的分辨率。后者可以使用小型 FPGA 来完成。

您可以阅读直接数字合成 (DDS) 方法。有些芯片可以做 DDS,但可能没有这么宽的位宽。

铷时钟模块可以在过剩市场上买到,或者来自 Microsemi 等制造商。