在本教程结束时,您将能够检测运动及其方向,并根据检测到的运动触发中断。
我们的防护罩使用 60GHz 雷达技术来检测 7m 范围内的运动及其方向。它提供仅 20x6.25mm 的小尺寸和低功耗,为许多应用创造了创新、直观的传感功能。小型运动传感器集成天线并在内部处理原始雷达信号,无需任何外部微控制器即可操作设备。
仅使用四个引脚就可以非常轻松地与防护罩连接:
带有 GND 和 Vin(1.5V 至 5V)的电源可以连接到微控制器引脚 Vcc 和 GND。相位检测输出 (P out) 引脚表示方向,而目标检测输出 (T out) 引脚表示雷达传感器检测到的运动。BGT60 可以轻松插入 Arduino MKR1000 板的接头(Vcc、GND、T out - A1 和 P out - A2)
我们为 60GHz 雷达屏蔽开发的库称为“radar-bgt60”。使用 Arduino IDE,通过 Sketch -> Include library -> Library Manager 安装 Radar 库。雷达库包括八个基本 API 函数,我们稍后会在各种示例中使用它们。
在我们的Arduino API 描述中找到更多详细信息。
要将草图上传到您的板上,您必须先选择所需的平台。在此示例中,我们使用 Arduino MKR1000 板。转到工具 -> 董事会 -> 董事会经理。在那里你搜索你的“Arduino MKR1000”,你会找到需要安装的包“Arduino SAMD Boards”。
为了现在上传草图,您还必须选择正确的 COM 端口。有一个非常简单的方法可以做到这一点。拔下连接的 Arduino,然后检查Tool -> Port下可用的 COM-Ports 。现在连接您的 Arduino 并再次检查端口。现在你应该看到一个新的,以前没有的。这是正确的,请选择它。
在第一个简单示例中,我们想使用 getMotion() 函数来识别传感器环境中的运动。从文件 -> 示例 -> 雷达-bgt60 -> 运动检测中获取代码。
/*!
* \name motionDetection
* \author Infineon Technologies AG
* \copyright 2021 Infineon Technologies AG
* \brief This example detects the motion of an object
* \details This example demonstrates how to detect a moving object while the
* BGT60LTR11AIP shield is connected to Arduino compatible
* boards using polling method.
*
* Connection details:
* --------------------------------------------------
* Pin on shield Connected to pin on Arduino
* --------------------------------------------------
* TD depends on Arduino board
* PD depends on Arduino board
* GND GND
* Vin VCC (3.3V or 5V - depends on Arduino board)
* --------------------------------------------------
*
* Decoding on-board LED output of BGT60LTR11AIP shield:
*
* - Red LED indicates the output of direction of motion once target is detected (PD)
* ---------------------------------------------
* LED State Output explanation
* ---------------------------------------------
* Red ON Departing target
* OFF Approaching target
* ---------------------------------------------
*
* - Green LED indicates the output of target in motion detection (TD)
* ---------------------------------------------
* LED State Output explanation
* ---------------------------------------------
* Green ON Moving target detected
* OFF No target detected
* ---------------------------------------------
*
* SPDX-License-Identifier: MIT
*/
#include
/* Include library main header */
#include
/* Include Arduino platform header */
#include
/*
* In case no supported platform is defined, the
* PD and TD pin will be set to the values below.
*/
#ifndef TD
#define TD 15
#endif
#ifndef PD
#define PD 16
#endif
/* Create radar object with following arguments:
* TD : Target Detect Pin
* PD : Phase Detect Pin */
Bgt60Ino radarShield(TD, PD);
/* Begin setup function - takes care of initializations and executes only once post reset */
void setup()
{
/* Set the baud rate for sending messages to the serial monitor */
Serial.begin(9600);
// Configures the GPIO pins to input mode
Error_t init_status = radarShield.init();
/* Check if the initialization was successful */
if (OK != init_status) {
Serial.println("Init failed.");
}
else {
Serial.println("Init successful.");
}
}
/* Begin loop function - this part of code is executed continuously until external termination */
void loop()
{
/* Initialize the variable to NO_MOTION to be able to record new events */
Bgt60::Motion_t motion = Bgt60::NO_MOTION;
/* The getMotion() API does two things:
1. Returns the success or failure to detect moving object as a message of type Error_t.
Any value other than OK indicates failure
2. Sets recent event in "motion" variable. Events can be: NO_MOTION or MOTION */
Error_t err = radarShield.getMotion(motion);
/* Check if API execution is successful */
if(err == OK)
{
/* Cases based on value set in motion variable */
switch (motion)
{
/* Variable "motion" is set to MOTION when moving target is detected */
case Bgt60::MOTION:
Serial.println("Target in motion detected!");
break;
/* Variable "motion" is set to NO_MOTION when moving target is not present */
case Bgt60::NO_MOTION:
Serial.println("No target in motion detected.");
break;
}
}
/* API execution returned error */
else {
Serial.println("Error occurred!");
}
/* Reducing the frequency of the measurements */
delay(500);
}
没有注释,代码只有 50 行。在我们逐步讨论之后,我们将上传示例。
#include
#include
#include
首先,我们包含了来自 Arduino 的主库和用于 BGT60 雷达传感器的库。
#ifndef TD
#define TD 15
#endif
#ifndef PD
#define PD 16
#endif
Bgt60Ino radarShield(TD, PD);
if 条件检查是否定义了 TD 和 PD。它们代表我们的引脚相位检测和硬件的目标检测。在我们的例子中,它们已经设置好了,因为我们之前定义了支持的平台 Arduino MKR1000。如果我们选择另一个微控制器(不是来自 Arduino),这一步是指定未知引脚的必要步骤。行“Bgt60Ino radarShield(TD, PD);” 使用教练用两个针创建一个雷达对象。
void setup()
{
Serial.begin(9600);
// Configures the GPIO pins to input mode
Error_t init_status = radarShield.init();
if (OK != init_status) {
Serial.println("Init failed.");
}
else {
Serial.println("Init successful.");
}
}
在函数“setup”中是我们程序的初始化。当我们上传草图时它只执行一次。“Serial.begin()”函数设置波特率,它定义了向监视器发送消息的传输速度。现在我们使用库的 API 函数之一“intit()”来初始化之前的 Bgt60 类对象“radarShield”。因此,引脚将设置为输入模式。如果初始化成功,函数返回“OK”。为了以用户身份查看初始化是否有效,我们打印 init 函数的结果。
void loop()
{
Bgt60::Motion_t motion = Bgt60::NO_MOTION;
Error_t err = radarShield.getMotion(motion);
“loop()”函数是代码的一部分,它一遍又一遍地重复。首先,我们拒绝变量“运动”以保存检测到的运动。有两种可能的状态。一开始我们将其设置为“Bgt60::NO_MOTION”。
在下一行中,我们在“radarShield”对象上使用函数“getMotion()”。该函数的传递参数是运动变量。当传感器检测到运动时,该函数将变量设置为“Bgt60::MOTION” . 如果整个函数成功,“OK”将保存在“Error_t”变量中。
if(err == OK)
{
switch (motion)
{
case Bgt60::MOTION:
Serial.println("Target in motion detected!");
break;
case Bgt60::NO_MOTION:
Serial.println("No target in motion detected.");
break;
}
}
else {
Serial.println("Error occurred!");
}
delay(500);
}
在最后一部分,我们检查函数是否成功。在这种情况下,如果变量“motion”是“Bgt60::MOTION”或“Bgt60::NO_MOTION”,我们将启动 switch case 条件并打印解决方案。最后我们开始一个延迟,它代表两个循环段落之间的暂停。
现在我们了解了整个代码并准备上传它。如果到目前为止还没有完成,您可以编译按钮 1 上的代码。使用 2 将草图上传到板上。要查看我们打印的内容以及传感器是否检测到运动,您必须在 3 上打开显示器。
当周围的一切完全静止时,您可以在监视器上读取“未检测到运动中的目标”。但是,如果您在距离传感器 5 米的范围内有运动,您的输出就是“检测到运动中的目标!”。
在成功检测到运动之后,我们还想知道这个运动的方向。因此,库、对象创建和设置功能完全相同。
Bgt60::Direction_t direction = Bgt60::NO_DIR;
Error_t err = radarShield.getDirection(direction);
循环中的代码也和之前类似,但现在我们为方向做。首先我们需要一个变量来存储方向。其次,我们使用 API 函数“getDirection()”。
if (err == OK)
{
switch (direction)
{
case Bgt60::APPROACHING:
Serial.println("Target is approaching!");
break;
case Bgt60::DEPARTING:
Serial.println("Target is departing!");
break;
case Bgt60::NO_DIR:
Serial.println("Direction cannot be determined since no motion was detected!");
break;
}
}
else{
Serial.println("Error occurred!");
}
方向变量有三种可能的状态。我们有两个不同的方向:接近和离开。也有可能,我们根本没有运动,因此没有方向。如果 API 函数有效,它会为错误变量返回“OK”。只有当它成功时,我们才会开始一个 switch-case 条件,我们在离开、接近和无方向之间做出决定。每次延迟后都会打印当前状态。
可能的监视器输出在上图中。要创建它,您首先将手移向传感器,然后再移开。
作为最后一个例子,让我们展示如何使用中断功能。当您启用中断时,处理器会停止其当前活动并保存其状态。相反,它同时执行一个称为中断服务程序 (ISR) 的功能。在我们的示例中,当检测到的运动或方向的状态发生变化时会触发中断。因此,代码中的库和对象创建仍然与上两个示例中的相同。
init_status = radarShield.enableInterrupt(cBackFunct);
if (OK != init_status)
Serial.println("Interrupt init failed.");
else
Serial.println("Interrupt init successful.");
}
在 setup 函数中,我们像以前一样设置波特率并初始化我们的对象。此外,我们现在激活中断。函数“enableInterrupt()”打开硬件中断。“cBackFunct”函数从中断开始。此外,我们得到一个状态变量,我们可以使用它检查启用中断的 API 函数是否有效。
/* Definition and initialization of the interrupt active flag */
volatile static bool intActive = false;
/* User defined callback function */
void cBackFunct(void)
{
if ( ! intActive ) {
/* Set the interrupt active flag to avoid parallel execution of this function multiple times. */
intActive = true;
/* Create variables to store the state of the motion as well as the direction */
Bgt60::Motion_t motion = Bgt60::NO_MOTION;
Bgt60::Direction_t direction = Bgt60::NO_DIR;
/* Now check what happend, first check if a motion was detected or is
not detected anymore */
Error_t err = radarShield.getMotion(motion);
/* Check if API execution is successful */
if(OK == err)
{
/* In case motion is detected */
if(Bgt60::MOTION == motion){
Serial.println("Target in motion was detected!");
/* Check the direction of the detected motion */
err = radarShield.getDirection(direction);
if(OK == err)
{
/* In case the target is approaching */
if(Bgt60::APPROACHING == direction){
Serial.println("The target is approaching!");
}
/* In case the target is departing */
else{
Serial.println("The target is departing!");
}
}
/* API execution returned error */
else{
Serial.println("Error has occurred during the determination of the direction!");
}
}
/* No motion is detected */
else{
Serial.println("No target in motion detected!");
}
}
/* API execution returned errord */
else {
Serial.println("Error has occurred during the determination of the direction!");
}
Serial.println("\n--------------------------------------\n");
/* Release the interrupt active flag to allow a new call of this callback function. */
intActive = false;
}
}
“cBackFunct”代表中断服务程序(ISR)。我们将它写在 setup 函数之前的单独函数中。还。我们有一个局部变量,它是中断的活动标志。因此,它在 ISR 开始时设置为活动,在函数结束时设置为非活动。为避免多次并行执行此函数,“cBackFunct”检查活动标志之前是否处于非活动状态。该函数中的其他所有内容都类似于方向检测。我们首先使用已知函数来检查运动,然后分离运动的两个方向。我们打印相应的运动状态和方向。之后,我们打印一个视觉边框以保持概览。
void loop()
{
// Here you can do something else in parallel while waiting for an interrupt.
delay(1000);
}
在我们的循环函数中,我们现在只有延迟。我们可以在那里放置任何代码,这些代码应该在没有发生运动或方向变化的情况下执行。为了更容易理解中断的工作方式,您也可以在循环中打印一些内容。
监视器输出在每个边界后发生变化。这是因为我们只有在发生变化时才开始中断。打印输出之间的时间不再像以前那样有规律,现在取决于中断。
如果我们不再需要中断,例如一段时间后,我们可以使用函数“disableInterrupt()”禁用它。之后只有我们在循环中的代码会被执行。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !