首页 > 解决方案 > 如何在伺服电机收到任何传感器的信号后停止一段时间?

问题描述

我正在开发一个基于 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");
  
  }
 }   

标签: c++automationarduinoembeddedservo

解决方案


根据我的评论,然后:

相反,您希望伺服器在不再检测到对象后的某个时间停留在位置 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 启动定时器。

然后是计时器。

  • 定时器溢出:对象消失后时间已过。向伺服发出命令以返回初始化。

推荐阅读