本文介绍如何在机器人项目中通过 Simulink® 和 Arduino® 建模和使用 Sharp® 红外传感器 (GP2Y0A02YK0F)。目的是展示如何使用基于模型的设计。对于某些机器人应用程序,此处使用的建模和过滤是多余的。即使是这种情况,如果发生意外情况,了解系统如何工作总是好的。选择正确的建模级别和系统复杂性是一项重要的工程技能。
在第一部分中,我们将专注于对传感器进行建模并获得可靠的距离测量。这种方法的一个优点是当没有检测到障碍物时它不会使用任何 CPU 时间。在第三篇文章中,我们会将传感器模型包含在移动机器人的仿真环境中。在第四篇也是最后一篇文章中,我们将在一个真实的机器人平台上测试所有部件。
在控制理论中,传感器、执行器和处理此类信号的元件的组合通常被称为“工厂”。植物模型很重要并且有很多用途。通过围绕将在 CPU 上运行的部件对系统进行建模,可以及早且廉价地测试设计。系统模拟在发现错误方面非常有效,而不会损坏硬件,甚至在某些情况下,在任何硬件可用之前也是如此。系统模型还允许对新想法进行实验。例如。具有合适的机器人导航系统模型的想法可以很容易地进行评估。有些可以丢弃,有些看起来更有希望的可以进一步开发。
植物建模是一个学习机会。创建了有关系统如何工作的知识,这对于软件的开发、调试非常有用,对于获得有关如何使用它的新想法甚至更重要。植物建模是一种知识创造活动,知识存储在其他人可以轻松获取的模型中。
什么是合适的植物模型?应该详细到什么程度?选择正确的细节层次是困难的。一些开发人员过度使用它,而另一些开发人员则忽略了重要的行为。在准确性、建模(和获取知识)所花费的时间和仿真时间之间需要权衡取舍。决定在特定情况下使用多少努力是一项随着时间的推移随着经验而发展的技能。没有正确的答案,系统开发可以从具有不同保真度的多个工厂模型中受益。例如,用于控制器评估的详细工厂模型和用于测试逻辑的细节较少的工厂模型。
工厂模型可以通过第一性原理或数据驱动建模获得。最常见的方法是使用它们的组合。在本文中,我们将使用类似于学习过程的临时方法。
这是工厂建模和传感器学习过程的第一步。将 +5V、GND 和传感器输出连接到模拟输入 0。检查数据表中的传感器引脚。
使用 Arduino IDE 和下面的草图在串行监视器上打印传感器读数。
即使传感器前面有固定障碍物,从传感器读取的值也会波动很大。在我的情况下,它在 152 和 191 之间变化。这可能只是传感器噪音吗?将示波器连接到传感器输出会提供线索:
频率为 1000 Hz 时,传感器输出的峰值约为 90 mV。传感器每毫秒发送一束红外光,并根据反射光照射到传感器的哪个元件输出电压电平。要了解有关传感器工作原理的更多信息,请查看本文。
似乎峰值由一种快速模式(初始峰值)和一种慢速模式组成。信号上也有一些噪音。可以对此进行更多详细说明并深入研究电气特性,但一些(经验)告诉我,这对于机器人项目来说已经足够了。
根据图表,数据表还显示输出电压电平是非线性的:
从任务 1 中我们了解到,传感器的输出信号包含三个分量:
非线性函数可以通过 Simulink 中的查找表轻松实现。从数据表中的图中测量得出:
table_data = [0 2.3 2.75 2.55 2 1.55 1.25 1.05 0.9 0.8 0.725 0.65 0.6 0.55 0.5 0.495 0.49];
breakpoints = [0 10 15 20 30 40 50 60 70 80 90 100 110 120 130 140 150] / 100;
plot(breakpoints, table_data);
title('Sensor output value');
xlabel('Distance (m)');
ylabel('Voltage (V)');
grid on;
测量噪声由带限白噪声建模。必须确定功率和采样时间参数。我通过测试不同的数字来做到这一点。对于采样时间,我从测量中知道峰值宽度略大于 0.1 ms,噪声应该更快。0.1 ms / 125 的值可以正常工作。功率逐渐降低,直到 Simulink 示波器显示与测量值相似的噪声水平。
数据驱动建模现在可用于使用系统识别工具箱获得动力学的传递函数。在这种情况下,我选择只添加两个传递函数。一个用于慢速动力学的一阶传递函数和一个用于快速动力学的二阶传递函数。脉冲发生器将驱动传递函数。
根据我的测量,我们看到慢速动态在脉冲期间上升了约 30 mV。这意味着静态增益应该约为 0.03。一阶函数的上升时间为:
静态增益 K = 0.03 我们得到:
这些都是很好的初始值,并通过一些手动调整使阶跃响应看起来像我最终得到的测量值:
对于二阶函数,我们有:
因为它应该比一阶函数更快,所以我选择 f = 100 kHz 和 xi = 0.7。
慢速和快速动态的范围输出:
将这些组件简单地添加在一起,生成的 Simulink 模型如下所示:
和模拟输出:
笔记!使用示波器测量传感器测量距离的电压表明,我的传感器提供的电压略低于数据表中的表格。这可能是由于传感器的个体差异和/或 Arduino 模拟输入中的电气特性造成的。为了安全起见,我将表格值保留在这里,如有必要,我可以稍后进行校准。
阅读传感器的数据表,我还发现建议在 Vcc 和 gnd 之间使用一个相当大的电容器,尽可能靠近传感器,以限制突发期间的峰值。除了大电容外,我还添加了一个 200 nF 的小电容,以抑制电源电压上的一些高频噪声。
为了进一步平滑传感器输出,我添加了一个简单的无源滤波器,即 RC 滤波器。
该滤波器的截止频率为:
为了至少过滤快速动态,截止频率应低于 100 kHz。此外,它不能太低,因为与传感器的距离变化会滞后。模拟是一个很好的工具,可以玩这样的设计,看看会发生什么并了解它是如何工作的。经过一些实验,我选择了大约 16 kHz 的截止频率。比意味着 2*pi*R*C = 1 / 16000。R 应尽可能低以避免静态误差,我发现 10 ohm 可用,然后 C = 1 uF。
应用电容器和滤波器并测量滤波后的输出,我得到以下结果:
这是电路:
为了模拟旁路电容器的影响,我简单地将脉冲生成的幅度减小到 0.1,从而得到输出的十分之一。我还增加了噪音以使其更准确。滤波器被实现为一阶滤波器,RC / (s + RC),参见下一个任务中的模型。模拟输出现在如下所示:
使用此处的模型无法捕捉旁路电容器的影响,因为这需要更详细的传感器电气特性模型。通过减少尖峰的近似值对于我们的机器人应用来说已经足够了。
可以使用SimElectronics更详细地以特定领域的方式实现该工厂模型。
要在可以在 Arduino 目标上执行的模型中使用测量信号,必须提供两件事;采样时间和正确的数据类型。Arduino 模拟输入模块输出一个 16 位无符号整数。在我们的应用程序中,我们选择了 100 ms 的采样时间。
使用默认参考电压 (5V) 的模数转换输出介于 0 (0V) 和 1023 (5V) 之间的值。为了转换我们测量的电压,我们需要将信号乘以 1023 并除以 5。在乘以和添加噪声之前,以 100 ms 对连续信号进行采样。之前采样的原因是为了加快我们的模拟速度。如果在我们修改后对其进行采样,这些操作将不得不与模型的连续部分一起更频繁地完成,从而使我们的模拟陷入困境。
进行乘法运算的增益模块还将信号转换为无符号 16 位整数并使信号饱和以避免负输入电压的回卷。这可以防止输入电压为 0 且噪声小于 0 的情况。如果没有这种饱和,结果将是一个非常大的数字。
请注意,5V 最大输入没有饱和。在模型中,输出将持续超过 1023。在实际电路板上,电路板的输入引脚可能会损坏。最好的方法是检查过电压并至少给出模拟警告,但这留作练习。例如,仅仅添加一个饱和块意味着这种错误情况不容易被仿真检测到,并可能导致硬件故障。
读取模拟输入会给我们一个介于 0 到 1023 之间的值,对应于 0 V 到 5 V。有很多方法可以将此信号转换为有用的距离。这里我选择使用查找表,因为距离是非线性的,并且查找表易于校准。
我们现在可以重用我们在传感器建模和采样过程中学到的知识。第一步是反转用于传感器的查找表。这是有问题的,因为该函数在反转时不是单调的。例如,对于 10 cm 和 25 cm 的距离,传感器提供大致相同的输出电压。为了解决这个问题,我们需要删除前两个值:0 和 10 cm。结果是只能测量 20 到 150 厘米之间的范围。这也是传感器根据规格的工作范围。这意味着如果我们在 10 厘米处有障碍物,Arduino 软件会认为它在 25 厘米处。这必须在系统其余部分的设计中加以考虑。解决它的一些方法是在最小范围之前停止,
除了反转表格,我们还需要对采样进行补偿。表中的断点包含从 0.49 V 到 2.75 V 的电压,但我们读取的值是从 0 到 1023 的整数。乘以 5 并除以 1023 应该可以得到正确的值。但是,这会给我们一个介于 0 和 5 之间的电压,并且整数不能提供足够的分辨率。因此,我们还乘以 1000 以获得以 mV 为单位的整数值。我们对距离做同样的事情,并以毫米为单位获得输出范围测量值。
最后,我们放入一个检查阈值的块,如果范围高于 250 mm,则输出 0,如果低于 250 mm,则输出 1。此检查将用于在下一步点亮 Arduino 板上的用户 LED。
要进一步测试模型,请将斜坡作为距离并检查布尔输出是否在正确的距离处触发。
对采样和断点进行补偿的倒排表:
inv_table = uint16([150 140 130 120 110 100 90 80 70 60 50 40 30 20 15]*10);break_points = [490 495 500 550 600 650 725 800 900 1050 1250 1550 2000 2550 2750] * 1023/(5*1000);plot(break_points, inv_table);title('Distance table');ylabel('Distance output (mm)');xlabel('Sampled value');grid on;
完整的模型现在看起来像这样:
该系统的建模和高级设计现已完成。下一步是稍微清理模型并设计一个架构,让我们既可以模拟整个系统,又可以在目标硬件上运行算法。如果连接了 Arduino 输入块,则无法再使用植物模型。使实际的软件实现平台独立也是一个很好的设计。使用引用模型,我们可以创建三个模型:
完整的系统模型和 Arduino 平台模型现在可以组合成一个模型块,它引用软件和硬件模型。这为我们提供了以下信息:
系统型号:
和 Arduino 子系统:
请注意,software_6 是一个单独的模型,一个引用模型:
因此,为了运行软件模型,下面的平台模型包括 Arduino I/O 模块,并且还引用了 software_6 模型。
在连接了传感器、滤波器和电容器的目标上加载并运行 platform_6 模型。将物体移向和远离传感器,以查看用户 LED 何时亮起。
现在可以使用这个简单的应用程序来校准查找表。将障碍物放置在特定距离,例如 25 厘米,并使用 250 作为“比较块”内的值。通过轻轻移动物体,检查 LED 是否触发接近 25 厘米。如果它不亮,请将查找表的断点调整到 25 厘米附近。
使用查找表只是映射非线性函数的一种方法。试着想出一个与函数匹配的指数方程。
尝试用不同的材料检查传感器,例如深色织物和白纸。有区别吗?
对于某些模拟,计算时间可能很关键。并不总是需要噪声和尖峰的影响。在这种情况下,通过删除除查找表之外的所有内容来制作简单的工厂模型可能是有益的。从软件的角度来看,采样中的一些波动应该是唯一的区别。具有更高保真度的模型仍然可以偶尔用于检查它是否也适用于更多细节。创建这些不同的工厂模型并比较软件输出。差异有多大?
这是一个小例子,展示了基于模型的设计的一些有趣方面。建模的主要收获是对传感器工作原理的了解和理解。在不同条件下的实际应用中使用传感器时,这些知识很重要。
在下一篇文章中,我们将实现一个新的 Arduino 模块,该模块通过中断捕获范围阈值,而不是像本文中那样检查每个时间步的范围。中断方法的优点是在阈值触发之前不需要任何 CPU 执行。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !