我想我需要根据你的问题和评论澄清一些事情。
从 micaZ motes 上的加速度计读取单个样本的工作原理如下:
- 打开加速度计。
- 等待 17 毫秒。根据 ADXL202E(加速度计)数据表,启动时间为 16.3 ms。这是因为这个特定的硬件能够提供第一次读数,而不是在通电后立即提供,而是有一些延迟。如果你减少这个延迟,你可能会得到一个错误的读数,但是,行为是不确定的,所以你有时可能会得到一个正确的读数,或者结果可能取决于环境条件,例如环境温度。将这个 17 毫秒的延迟更改为较低的值肯定是个坏主意。
- 从模数转换器 (ADC) 读取值(在两个轴上),ADC 是一个 MCU 组件,可将加速度计的模拟输出电压转换为数字值(整数)。ADC 采样的速度与加速度计的参数无关:它是另一个硬件。
- 关闭加速度计。
这就是您调用Read.read()
代码时发生的情况。您会看到可以采样的最大频率是每 17 毫秒一次,即每秒 58 个样本。由于 MCU 的一些开销或计时器的不准确性,它甚至可能会更小一些。当您通过循环或每个固定间隔调用进行采样时,这是正确Read.read()
的,因为此调用本身持续不少于 17 毫秒(我的意思是命令和事件之间的延迟)。
您可能想要做的是:
- 打开加速度计。
- 等待 17 毫秒。
- 执行一系列读取。
- 关闭加速度计。
如果这样做,则一组样本会有一个 17 毫秒的延迟,而不是每个样本的延迟。重要的是,这些步骤与您用于执行读数的界面无关。您可以Read.read()
在您的应用程序中多次调用,但是,它不能与read
已为此加速度计实现的命令的实现相同,因为现有实现负责打开和关闭加速度计,并且在读取每个之前等待 17 毫秒样本。为方便起见,您可以ReadStream
改为实现该接口并在您的应用程序中调用它一次。
此外,您写道,它ReadStream
使用了微秒计时器,并且与 ADC 的 17 毫秒建立时间无关。那句话是完全错误的。首先,你不能说一个接口使用或不使用定时器。接口只是一组没有定义的命令和事件。接口的特定实现可以使用定时器。和接口可以通过各种硬件组件在不同平台上多次实现,例如加速度计、温度计、湿度计、磁力计等Read
。ReadStream
其次,17 毫秒的建立时间是指加速度计,而不是 ADC。无论您使用哪个接口,Read
或者ReadStream
,驱动程序使用哪个计时器,毫秒或微秒,加速计通电后始终需要 17 毫秒的延迟。正如我所提到的,您可能希望每次读取一次而不是每次读取一次。
TinyOS 源代码似乎已经包含了加速度计驱动程序的实现,ReadStream
它提供了允许您连续采样的接口。查看AccelXStreamC
和AccelYStreamC
组件(在tos/sensorboards/mts300/中)。
该ReadStream
界面由两个命令组成。postBuffer(val_t *buf, uint16_t count)
被调用来为样本提供缓冲区。在加速度计驱动程序中,val_t
定义为uint16_t
。您可以一一发布多个缓冲区。此命令尚未开始采样和填充缓冲区。为此,有一个read(uint32_t usPeriod)
命令,它指示设备通过以指定周期(以微秒为单位)进行采样来开始填充缓冲区。当缓冲区已满时,您会收到一个事件bufferDone(error_t result, val_t *buf, uint16_t count)
,并且组件开始填充下一个缓冲区(如果有)。如果没有剩余缓冲区,您还会得到一个 event readDone(error_t result, uint32_t usActualPeriod)
,它会向您的应用程序传递一个参数usActualPeriod
,该参数指示实际的采样周期,并且可能与您在调用时请求的周期不同(尤其是更高)read
由于一些硬件限制。
所以解决方案是使用andReadStream
提供的接口(或者可能是一些使用它们的更高级别的组件)并将预期的时间(以微秒为单位)传递给命令。如果实际周期低于您的预期,这意味着由于硬件限制或未在 ADC 驱动程序中实现,不可能以更高的速率进行采样。在第二种情况下,您可以尝试修复驱动程序,尽管它需要良好的低级编程知识。此平台的 ADC 驱动程序源代码位于tos/chips/atm128/adc中。AccelXStreamC
AccelYStreamC
read