c++ - 如何在伺服电机收到任何传感器的信号后停止一段时间?
问题描述
我正在开发一个基于 Arduino Uno 的简单项目,名为“废物分类系统”。为此,我使用了 3 个不同的传感器(IR、感应接近和雨滴)和 3 个微型伺服电机。基本上它的作用是,不同的伺服电机根据它从移动的传送带检测到的物体类型(如非金属、湿的或金属)旋转。因此,一切正常,但我面临的唯一问题是,在传感器感应到任何物体后,我无法将伺服电机保持在较新的位置一段时间。当物体不再位于传感器前面时,它会返回到其初始位置。
我尝试在代码的不同部分使用 delay() 函数,但它无法正常工作。就像我使用延迟(3000)一样;在感应到不想要的物体后,伺服系统也会在 3 秒后移动。
如果你能以某种方式帮助我,我将非常感激你。提前致谢 :)
我使用的代码;
#include <Servo.h>
Servo tap_servo_1;
Servo tap_servo_2;
Servo tap_servo_3;
// here No. 1 is for Inductive sensor, No.2 is for Raindrop sensor and No.3 is for IR sensor //
int sensor_pin_1 = 4;
int tap_servo_pin_1 =5;
int sensor_pin_2 =2;
int tap_servo_pin_2 =3;
int sensor_pin_3 =8;
int tap_servo_pin_3 =9;
int val_1;
int val_2;
int val_3;
void setup()
{
pinMode(sensor_pin_1,INPUT);
tap_servo_1.attach(tap_servo_pin_1);
pinMode(sensor_pin_2,INPUT);
tap_servo_2.attach(tap_servo_pin_2);
pinMode(sensor_pin_3,INPUT);
tap_servo_3.attach(tap_servo_pin_3);
}
void loop()
{
val_1 = digitalRead(sensor_pin_1);
if(val_1==0)
{tap_servo_1.write(10);
}
if (val_1==1)
{tap_servo_1.write(70);
Serial.println("Waste detected is: Non-Metal");
}
val_2 = digitalRead(sensor_pin_2);
if(val_2==0)
{tap_servo_2.write(0);
}
if (val_2==1)
{tap_servo_2.write(75);
Serial.println("Waste detected is: Wet");
}
val_3 = digitalRead(sensor_pin_3);
if (val_3==0)
{tap_servo_3.write(10);
}
if (val_3==1)
{tap_servo_3.write(70);
Serial.println("Waste detected is: Metal");
}
}
解决方案
根据我的评论,然后:
相反,您希望伺服器在不再检测到对象后的某个时间停留在位置 70。
您需要在识别对象后忽略传感器值的东西。目前,每次循环迭代(比系统机制快得多)都会检查传感器值,因此您会看到伺服系统立即返回到初始位置。让我们添加一个 3 秒的不应期。在此期间,您不想检查 val_x 传感器。
问题sleep
在于它是一个阻塞函数,整个程序都会挂起。相反,您希望在检测到对象后“冻结”时间,并在经过确定的时间后再次检查。
// Store time here - init at zero
unsigned long non_metal_detect_time = 0;
unsigned long wet_detect_time = 0;
unsigned long metal_detect_time = 0;
unsigned long ms_from_detection_non_metal;
unsigned long ms_from_detection_metal;
unsigned long ms_from_detection_wet;
void loop()
{
val_1 = digitalRead(sensor_pin_1);
ms_from_detection_non_metal = millis() - non_metal_detect_time ;
// we care about this value only if 3s have passed otherwise we
// ignore the value from the sensor even if the object is not there
if(val_1==0 && ms_from_detection_non_metal > 3000 )
{
tap_servo_1.write(10);
}
if (val_1==1)
{
// save when it's detected
non_metal_detect_time = millis();
tap_servo_1.write(70);
Serial.println("Waste detected is: Non-Metal");
}
// You can do the same modifications for the other sensors.
}
相反,另一个想法需要更复杂的软件,但它也会更好地利用您的硬件资源。我给你思路。
您可以使用边缘检测从 GPIO 触发多个中断:
- 0 -> 1:检测到对象。ISR 向伺服系统发出命令。停止计时器。
- 1 -> 0:对象已消失。ISR 启动定时器。
然后是计时器。
- 定时器溢出:对象消失后时间已过。向伺服发出命令以返回初始化。
推荐阅读
- c# - ASP.Net Core - 从“调试”文件夹创建本地 IIS 网站
- javascript - 找不到入口模块中的错误:错误:无法解析“*源*”
- html - 如何排除 R 中的某些节点?
- ios - 主线程检查器:在后台线程上调用的 UI API
- excel - 检查日期是否有效
- salesforce-lightning - 如何在 Lightning Web 组件中使用轮播请参阅下面的代码 + 需要一些示例示例如何在 lwc 中实现
- java - Java throws 关键字
- hibernate - 急切加载能解决 n+1 问题吗?(SpringBoot/休眠)
- regex - 如何限制用户不在 Angular 中输入十进制值?
- github - 在 JetBrains GoLand 上,为什么在 GitHub 上打开操作被禁用以及如何启用它?