我最近在为一项新设计进行实验,其中需要使用函数发生器。尽管新的函数发生器具有相当好的频率容差规格,但我需要获得更高的精度。用频率发生器、任意波形发生器和频率计数器获得更高精度的方法,是使用许多这些测试仪器上所提供的10MHz参考输入。由于没有这样的参考,而且我最近一直在玩Arduino Nano(下文简称Nano),我决定看看是否可以围绕Nano构建一个这样的设计。
图1显示了这种简单廉价的“无需校准”的设计的主要部件。该频率由10MHz压控晶体振荡器(VCXO)产生。该振荡器会产生约10MHz的频率,并具有合理的容差,但也有一个频率调整引脚,支持向上或向下进行调整。获得更精确的10MHz信号的诀窍,是为VCXO设置正确的调整,并在VCXO受到各种因素产生漂移时对其进行重新调整。让我们来看看其实现方法。
图1:无需校准的简单频率发生器的主要部件。
GPS模块可提供非常准确的每秒1个脉冲(1PPS)的信号。该脉冲看起来像一个每秒约100ms的脉冲。即使是用便宜的模块,该信号在几十纳秒的范围内通常也比较准确。这是生成精确10MHz信号的设计的外部参考。1PPS信号通过可产生中断的I/O线连接到Nano。该设计还具有一个32位计数器,可通过Nano对其进行读取和复位。将32位计数器连接到VCXO的输出,就可以用它来计算自上次复位后的VCXO周期数。最后一个主要部分是如何调整VCXO。
Nano没有DAC,但事实证明,它有一项简单功能,就是可控制其脉宽调制(PWM)输出,进而获得可调节的直流输出电压(滤波后)。一组简单的调用,即可以固定的频率输出5V PWM信号。PWM具有8位调节范围,因此如果想要2.5V输出,可以将PWM设置为128(50%占空比)。(注意,对于这组调用,Nano使用大约500Hz的频率,但这仅对滤波器设计比较重要。)所以,首先想到的是使用Nano的PWM输出,对其进行滤波,获得相对无纹波的直流电平,然后将其施加到VCXO的调整引脚。这样可以奏效,但问题是只有255个离散电平可以设置,这就可能不够。让我们更深入地了解一下。
我为该项目选择的VCXO是泰艺电子(Taitien)的TSEAACSANF-10.000000。它具有2ppm的初始频率容差,以及在调整引脚上使用0.5V至2.5V电压获得的约±12ppm的最大调整范围,该范围也称为“拉动范围”。因此,如果使用完整的255步PWM,就可以大约(2×12/255≈0.1ppm)的分辨率调整VCXO。这似乎对ppm精度没有太大的改进,所以我想出了使用两个PWM的想法:一个用于粗调,一个用于微调。为了保持设计简单,我选择只使用电阻而不使用运算放大器。这部分电路可以在图2中看到(这里还显示了2个滤波电容,我们将在后面讨论)。
图2:对旨在用作可调直流输出电压的PWM输出进行粗调和微调。
本质上,所看到的是一个平均电路,电路粗调部分的电阻为2kΩ,微调部分的电阻为270kΩ。最后一个2kΩ电阻用于将电压分压成调节引脚,提醒一下,这里需要2.5V最大值。VCXO调整电压可以很容易地使用叠加来求解,其值大约等于公式1。
VCXO调整电压=9.76×10-3×PWMCOARSE+144×10-6×PWMFINE (公式1)
其中,PWMCOARSE和PWMFINE的取值范围为0到255。该电路有时称为无源平均电路,如弥尔曼定理所述。现在,使用两个PWM使VCXO调整引脚的输出电压单调是不切实际的,因为电阻的精度需要非常高。这可以通过选择电阻值,使PWM微调的调整范围与后续的粗调范围相重叠来解决。
让我来举个例子:图2中所示的电阻值支持PWM粗调信号每一步移动大约9.8mV。PWM微调信号则是每步移动约0.14mV,即在其整个范围内移动大约36mV。由于微调范围大于粗调步长,因此总是会有很多重叠。
图3显示了几个粗调范围,以及如何配置微调值与之重叠。在后面对调整算法的讨论中,我将解释如何使用这种重叠。(请注意,图2中的两个100μF电容之所以选择此值,是为了将PWM波形的纹波保持在0.14mV微调步长以下。为了帮助滤波,可使用代码将PWM频率提高到大约31kHz。)
图3:微调范围和粗调步长重叠的图表说明。
将所有这些放到一起,操作如下所示:上电后,Nano将PWM粗调和PWM微调设置为初始值(某个中间值),然后等待,直到它检测到来自GPS模块的1PPS信号。然后,在下一个1PPS信号中断时,Nano将32位计数器复位。然后计数器开始计算来自VCXO的周期数。在收到后续1PPS中断后,Nano捕获并读取32位计数器,该计数器的计数值应为10,000,000。如果计数值小于10,000,000,则向上调整PWM微调值。如果微调前的PWM微调值为255,则使PWM粗调值递增,并将PWM微调值设置为127(中间值)。如果计数值大于10,000,000,则向下调整PWM微调值。如果微调前PWM微调值为0,则使PWM粗调值递减,将PWM微调值设置为127(中间值)。可以看到,将微调过程与多个粗调值相重叠,可以使该算法安全地寻找合适的值,但这在搜索速度方面有些低效。
这实际上是调整的第一阶段。如果只测量一秒的计数值,则无法获得超过0.1ppm的精度。因此,代码的第二阶段支持32位计数器通过等待10次中断来累积10秒。现在计数值就可以上升到100,000,000,也可以调整到0.01ppm范围(即10ppb)。前两个阶段用于更快地接近10MHz目标值。第三个连续操作阶段可计数100秒,等待100次中断,然后再读取计数器。这样就达到了1,000,000,000的预期计数,从而支持调整到1ppb。但是PWM实际上可以调整到多少呢?如前所述,PWM微调每步移动大约0.14mV,VCXO可在0.5V至2.5V范围内实现约±12ppm调整。因此,每个微调步长将频率移动了大约(2×12ppm×(0.14mV/2.0V))≈0.0017ppm,即1.7ppb。所以,看起来我们有足够的调整来获得大约±1ppb。在代码中还可以看到更多,但这是寻找精确10MHz的本质。(此时应注意,Arduino Nano实际上具有16位PWM,但最大频率太低,以至于所需滤波器的建立时间很长——对于此应用来说太长了。)
至于性能,Nano可在LCD上输出各种统计数据,我的平均频率通常为10,000,000.00,平均误差为0.01Hz,该平均值的标准偏差为0.1ppb。因此,它可以将频率保持在接近几个ppb以内。这比我的函数发生器通过外部参考实现的效果要好两个数量级。
现在来看原理图。可以看到PWM平均电路将调节电压馈送到VCXO(这是唯一由Nano的3.3V电源供电的器件)。VCXO之后的电路用于对VCXO输出的削波正弦波进行方波整形。这个经过整形和缓冲的10MHz方波信号,不仅会发送到计数器,还会发送到外部BNC连接器。其中两个BNC连接器用于提供TTL信号。另一个配置有2个反相器门和一个33Ω电阻,用以产生大约50Ω的输出。第四个BNC连接器负责提供1PPS缓冲信号,供外部设备使用。
Nano下方是GPS模块。可以在网上以大约10美元到12美元的价格购买模块和天线。PCB如图4和图5所示。
图4:采用GPS规范的10MHz信号源的PCB。
图5:连接到封装的GPS规范振荡器PCB。
原理图中间是32位计数器(图1)。这个74LV8154(约1美元)实际上有两个16位计数器,可以将其配置为一个32位计数器。该计数器设计支持通过寻址4个单独字节以字节方式读取32位计数器。这需要4条地址线,而我在Nano上的I/O不够了,因此使用了74LS139将Nano中的2条线转换为计数器所需的4条线。
图6所示的LCD是采用标准I2C的20字符×4行LCD。原理图底部是一个简单的线性电源,它使用12V AC/DC适配器,将其调节至8V为Nano供电,并调节至5V为电路的各个部分供电。我使用线性电源来确保获得安静的Vcc平面。最后,有2个LED。一个绿色LED用于显示1PPS信号。第二个双色LED,当系统已紧密锁定到所需的10MHz时为绿色;如果尚未锁定,则为红色;如果系统处于保持状态,则交替显示红色/绿色。保持状态是用于在1PPS信号丢失期间保持当前设置的状态。为了检测1PPS信号的丢失,我使用了看门狗定时器(WDT)。我没有使用WDT来检测错误的代码执行问题,而是将WDT超时设置为2秒,并在1PPS中断例程中对其进行复位。如果系统没有收到1PPS中断,则WDT不会被复位。
图6:已完成的GPS规范振荡器封装,带LCD。
Nano的代码是使用Arduino IDE用C语言编写的。该代码基本上由1PPS中断驱动,该中断通过锁定32位计数器值(74LV8154的功能)、清除计数器和设置复位标志来进行快速响应。你可能已经发现下一次计数的某些部分丢失了,因为我们正在捕获计数器寄存器,然后将其清除,使其再次从0开始计数。(捕获和清除之间会有一定有限的时间。)这是真的,因此固件会通过将偏移值添加到原始计数器值来补偿此延迟。事实证明有16个缺失计数。这已经通过两种方式得到验证。首先,是通过在示波器上测量捕获寄存器信号和清除寄存器信号之间的时间。其次,我在不调整VCXO的情况下使用1秒和100秒的捕获(这些捕获通过延迟偏移值进行调整)运行了许多测试。1秒的捕获会重复100次并加起来。如果延迟偏移正确,则1秒的总和值(现在包含100个延迟偏移)应该等于100秒捕获的读数(其中包含1个延迟偏移)。在操作代码中,每次读取计数器时都会重新添加丢失的16个计数。
代码中的主循环(Arduino开发系统始终将经典C语言的“Main”函数作为循环运行)等待设置中断标志,并在设置好时读取74LV8154的锁定寄存器的值。接下来,它会检查这是否是“合理的”读数并且没有损坏(与10MHz的差异超过12ppm)。如果不好就扔掉。如果很好,它就会在一个小型boxcar平均器中处理该值。然后使用该平均值对PWM进行向上或向下调整,如上所述。然后它会决定它处于哪个阶段。第一阶段运行1秒计数并调整VCXO。这很快让我们了解到PWM设置。此阶段运行20秒。第二阶段需要10秒的计数读数来微调PWM设置。它设置为运行5次或50秒。最后阶段运行100秒读数,然后连续运行,随着温度或其他参数改变频率,不断调整以保持频率。
在最后阶段,会根据需要设置LED,并在每次读数后进行统计。这些统计数据可以在LCD上查看,并且可以使用电路中的防抖按钮在主循环中查看多个页面(图7)。统计数据包括瞬时频率、平均频率、当前ppb误差、ppb平均误差、ppb误差标准偏差、良好读数次数、不良读数次数、连续锁定时间、所看到的最大频率、所看到的最小频率,以及PWM粗调和微调设置。
图7:LCD上每次读数后进行的统计。
完整的项目信息可以在开源网站https://www.thingiverse.com/thing:5188330上找到(或者也可以在thingiverse.com中搜索“DamianB2”)。
项目信息包括带有原理图、PCB和PCBA BOM的完整KiCad项目。还包括完整的组装BOM、Arduino源代码、外壳的3D打印文件、GPS模块外壳的3D打印文件的链接、铭牌图片,以及各种注释等。
最后一个想法:有些人可能已经注意到,在设计采用GPS规范的振荡器(GPSDO)时,我们无意中创造了一个非常好的频率计数器的本质。我们将在后续对此进行研究。
Damian Bonicatto是一名咨询工程师,他在嵌入式硬件、固件和系统设计方面拥有数十年的经验。他拥有30项专利。
Phoenix Bonicatto是一名兼职记者。
(原文刊登于EDN美国版,参考链接:Simple GPS Disciplined 10MHz Reference uses Dual PWMs,由Franklin Zhao编译。)
本文为《电子技术设计》2022年9月刊杂志文章,版权所有,禁止转载。免费杂志订阅申请点击这里。