#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 запускает таймер.
А потом таймер.
- Переполнение таймера: прошло время после исчезновения объекта. Дайте команду сервомотору вернуться в исходное состояние.