Khepera III 工具箱/示例/i2c 气味板
此示例展示了如何将i2c 和i2c_stream_read 程序与 Khepera III 机器人的扩展板一起使用。这里使用的扩展板是 DISAL 开发的气味传感器板。凭借其三棵 VOC 传感器,该板允许测量空气中酒精(或其他物质)的浓度。这些传感器在内部以几千赫兹的频率采样,并且该板在一段时间内对它们进行积分(平均),以每秒提供几个样本给外部世界。
与外部世界的接口是 I2C 总线,连接到 Khepera III 机器人上的主 CPU。通过此 I2C 总线,可以配置该板,并且样本可以以两种不同的模式读取
- 在快照模式下,该板返回每个传感器的最后一个获取值。
- 在流模式下,该板将每个样本精确地发送一次。也就是说,一旦启动流,该板就会将其内部内存中的样本缓冲。为了避免缓冲区溢出,必须连续读取(并清空)此缓冲区。
在此示例中,我们将配置积分间隔并以快照和流模式读取样本。所有这些都是使用通用的i2c 和i2c_stream_read 程序手动完成的。当然,如果需要更频繁地执行此操作,建议为这些任务编写单独的程序。
启动一个 Khepera III 机器人(配备气味传感器板),并确保它连接到您的计算机。在本章的剩余部分,我们假设您的机器人通过 USB 连接。
将 I2C 程序复制到机器人上
computer> cd Programs
computer> k3put +usb i2c i2c_stream_read
您现在可以开始使用气味板了。
气味板是一个基于寄存器的设备,其 I2C 地址为 0x50。积分间隔存储在地址为 0x90 的 8 位寄存器中。
首先,让我们通过发出以下命令来读取此寄存器
robot> ./i2c 0x50 write 0x90 read 1
$DATA,1,2,write 90,read 0a
输出乍一看可能有点难以理解,但实际上非常容易阅读。上面的消息只是说在 I2C 总线上已传输了 2 条消息。第一条消息是具有单个字节 (0x90) 的写入消息,第二条消息是具有单个字节 (0x0a) 的读取消息。最后一个字节显然是寄存器的内容,并转换为十进制表示法的 10。
因此,我们当前的积分间隔是 10。请注意,气味板实际上使用二的幂比例来表示此间隔,也就是说,将间隔设置为 9 将产生每秒两倍的样本。
10 速度相当慢,让我们将间隔设置为 8,这快了 4 倍。要写入该寄存器,我们只需在寄存器号之后传输此新值即可
robot> ./i2c 0x50 write 0x90 8
$DATA,1,1,write 90 08
操作已确认!已发送一条消息,其中包含两个字节 (0x90, 0x08)。为了确保新值已被接受并存储在寄存器中,让我们再次读取该寄存器
robot> ./i2c 0x50 write 0x90 read 1
$DATA,1,2,write 90,read 08
一切看起来都正常。
气味板将最后一个获取的样本存储在寄存器 0x92(只读)中。一个样本实际上由每个传感器的值加上来自气味板上的内部振荡器的时戳组成。所有值都是 16 位的,因此需要 2 个字节,总共寄存器大小为 8 个字节。
要读取此寄存器,我们将发出以下命令
robot> ./i2c 0x50 write 0x92 read 8
$DATA,1,2,write 92,read 6b ... TODO
接收到的消息的解释如下:- 传感器 1:- 传感器 2:- 传感器 3:- 时间戳:0x6b 0x0d -> 107 + 13 * 256 = 3435
这种快照模式对于偶尔需要请求样本的情况非常方便,例如,要决定气味浓度是否超过某个阈值。但是,如果您想绘制气味浓度的演变过程,您可能希望一直查询该板以获取新值。如果您过于频繁地执行此操作,您可能会多次获得相同的样本。这是一种可以通过以下方式轻松演示的效果
robot> ./i2c -r 100 -d 0x50 write 0x92 read 8
它与上面的操作相同,但重复了 100 次。输出可能如下所示
TODO
在此示例中,每个样本已传输了大约 N(待办事项)次,但这将取决于 CPU 和 I2C 总线的负载。
为了获得气味浓度演变的连贯图,建议以一种每个样本精确传输一次的方式“流化”这些样本。
气味板确实提供了一个 VOC 流寄存器 (0x93)。使用i2c 程序读取此寄存器有点痛苦,因为流化需要发送多个(不同的)消息。
幸运的是,还有另一个程序 -i2c_stream_read - 它会自动完成所有这些操作。此程序将 I2C 设备地址 (0x50)、流寄存器 (0x93) 和块长度 (8) 作为参数
robot> ./i2c_stream_read 0x50 stream 0x93 8
并将返回类似于以下内容
$BLOCK,0,1,A1 32 30 00 30 20 61
$BLOCK,1,1,BC 30 30 00 30 EB 52
$BLOCK,2,1,BD 31 30 00 30 64 54
$BLOCK,3,1,BE 32 30 00 30 D8 54
$BLOCK,4,1,BF 32 30 00 30 6B 53
$BLOCK,5,1,C0 31 30 00 30 9F 52
...
每行对应一个已传输的 8 字节数据块。块中的第一个字节是状态字节,指示缓冲区中剩余的样本数量(包括当前传输的样本),并在第二列中打印(此处全部为 1)。以十六进制表示法打印的 7 个数据字节构成最后一列。
气味传感器值以每个块的最后 6 个数据字节编码。例如,在所获得的块中,我们获得了以下值:- 传感器 1:- 传感器 2:- 传感器 3
要绘制气味浓度的演变过程,我们只需要将i2c_stream_read 程序的输出转换为 Matlab 可以读取的内容,然后在其中绘制即可。
首先,让我们从计算机上启动程序并将输出重定向到文件中
computer> ssh [email protected] "/root/your_username/i2c_stream_read 0x50 0x93 8" > odor_stream
一旦您觉得收集了足够多的样本,请按 Ctrl-C 停止程序。
使用parse_stream.pl 将样本转换为具有制表符分隔值的文本文件,即
computer> ./parse_stream < odor_stream > matlab_odor_stream
最后,启动 Matlab 并键入
>> plot_odor
此 Matlab 脚本(m 文件)将加载matlab_odor_stream 文件并绘制三条曲线。