Как остановить серводвигатель на некоторое время после того, как он получит сигнал от любого датчика?

#c #automation #arduino #embedded #servo

Вопрос:

Я работаю над простым проектом на базе Arduino Uno под названием «Система разделения отходов». Для этого я использовал 3 различных датчика (ИК, индуктивный датчик приближения и Каплю дождя) и 3 микро-серводвигателя. В основном он делает то, что другой серводвигатель вращается в зависимости от типа объекта, который он обнаруживает с движущегося конвейера (например, неметаллический, влажный или металлический). Итак, все работает нормально, но единственная проблема, с которой я сталкиваюсь, заключается в том, что я не могу некоторое время удерживать серводвигатель в новом положении после того, как датчик обнаружит какой-либо объект. Он возвращается в исходное положение после того, как объект больше не находится перед датчиком.

Я пытался использовать функцию delay() в разных частях кода, но она работает неправильно. Например, если я использую задержку(3000); сервопривод также перемещается через 3 секунды после обнаружения нежелательного объекта.

Я был бы так благодарен вам, если бы вы мне как-нибудь помогли. Заранее спасибо 🙂

Код, который я использовал;

  #include lt;Servo.hgt; 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");    }  }    

Комментарии:

1. Дайте мне понять, если я пойму, в чем проблема. Давайте сосредоточимся на первом датчике. Вы получаете 1 от sensor_pin_1, а val_1 остается на 1 в течение всего времени обнаружения объекта. Как только объекта больше нет, val_1 возвращается к 0, и, следовательно, сервопривод возвращается в положение 10. Вместо этого вы хотите, чтобы сервопривод оставался в положении 70 некоторое время после того, как объект больше не будет обнаружен. Верно?

2. @FrAxl93 Да, ты правильно понял.

Ответ №1:

Основываясь на моем комментарии, тогда:

Вместо этого вы хотите, чтобы сервопривод оставался в положении 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 amp;amp; ms_from_detection_non_metal gt; 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 -gt; 1: объект обнаружен. ISR отдает команду сервоприводу. Таймер остановки.
  • 1 -gt; 0: объект исчез. ISR запускает таймер.

А потом таймер.

  • Переполнение таймера: прошло время после исчезновения объекта. Дайте команду сервомотору вернуться в исходное состояние.