Как остановить зацикливание сервопривода, если датчик не обнаруживает движения?

servo loop

У меня есть этот проект с моим Arduino UNO, где я хочу, чтобы мой серводвигатель SG90 шел на полной скорости до 180 градусов, когда датчик PIR посылает ВЫСОКОЕ значение, и медленно возвращался к нулю, когда значение НИЗКОЕ.

У меня есть этот код, работающий там, где сервопривод возвращается на полную скорость к нулю:

#include <Servo.h>

Servo myservo; //создает объект servo
int pos = 0; //переменная для хранения положения сервопривода
//количество времени, которое мы даем датчику для калибровки(10-60 секунд в соответствии с таблицей данных)
int calibrationTime = 30;
//время, когда датчик выдает низкий импульс
long unsigned int lowIn;
//количество миллисекунд датчик должен быть низким
//прежде чем мы предположим, что все движение остановилось
long unsigned int pause = 5000;
boolean lockLow = true;
boolean takeLowTime;
int pir = 12; //цифровой вывод, подключенный к выходу PIR
int pirPos = 13; //подключается к выводу 5V PIR

void setup() {
  myservo.attach(4); //прикрепляет сервопривод к контакту 4
  Serial.begin(9600); //начинает последовательную связь
  pinMode(pir, INPUT);
  pinMode(pirPos, OUTPUT);
  digitalWrite(pirPos, HIGH);
  //время калибровки
  
  Serial.println("calibrating sensor ");
  for (int i = 0; i < calibrationTime; i++) {
    Serial.print(calibrationTime - i);
    Serial.print("-");
    delay(1000);
  }
  Serial.println();
  Serial.println("done");
  
  //это ждет, пока выход PIR не станет низким, прежде чем завершить настройку
  while (digitalRead(pir) == HIGH) {
    delay(500);
  }
  
  Serial.print("SENSOR ACTIVE");
}

void loop() {
  if (digitalRead(pir) == HIGH)
    myservo.write(180);              // скажите сервоприводу перейти в позицию в переменной 'pos'
  Serial.print("Motion detected!");

  if (digitalRead(pir) == LOW)
    myservo.write(0);              // скажите сервоприводу перейти в позицию в переменной 'pos'
  Serial.print("Motion ended!");
}

Мне бы хотелось, чтобы сервопривод медленно возвращался к нулю, поэтому я попробовал следующее :

#include <Servo.h>

Servo myservo; //создает объект servo
int pos = 0; //переменная для хранения положения сервопривода
//количество времени, которое мы даем датчику для калибровки(10-60 секунд в соответствии с таблицей данных)
int calibrationTime = 30;
//время, когда датчик выдает низкий импульс
long unsigned int lowIn;
//количество миллисекунд датчик должен быть низким
//прежде чем мы предположим, что все движение остановилось
long unsigned int pause = 5000;
boolean lockLow = true;
boolean takeLowTime;
int pir = 12; //цифровой вывод, подключенный к выходу PIR
int pirPos = 13; //подключается к выводу 5V PIR

void setup() {
  myservo.attach(4); //прикрепляет сервопривод к контакту 4
  Serial.begin(9600); //начинает последовательную связь
  pinMode(pir, INPUT);
  pinMode(pirPos, OUTPUT);
  digitalWrite(pirPos, HIGH);
  
  //время калибровки
  Serial.println("calibrating sensor ");
  for (int i = 0; i < calibrationTime; i++) {
    Serial.print(calibrationTime - i);
    Serial.print("-");
    delay(1000);
  }
  Serial.println();
  Serial.println("done");
  
  //это ждет, пока выход PIR не станет низким, прежде чем завершить настройку
  while (digitalRead(pir) == HIGH) {
    delay(500);
  }
  
  Serial.print("SENSOR ACTIVE");
}


void loop() {
  if (digitalRead(pir) == HIGH)
    myservo.write(180);              // скажите сервоприводу перейти в позицию в переменной 'pos'
    
  Serial.print("Motion detected!");

  if (digitalRead(pir) == LOW)
    for (pos = 180; pos >= 0; pos -= 1) { // переходит от 180 градусов к 0 градусам
      myservo.write(pos);              // скажите сервоприводу перейти в позицию в переменной 'pos'
      delay(15);                       // ждет 15 мс, пока сервопривод достигнет нужного положения.
    }
    
  Serial.print("Motion ended!");
}

Проблема в том, что с этим кодом сервопривод медленно возвращается к нулю, но затем набирает полную скорость до 180 и снова, и снова ...

Есть идеи? Я новичок в Arduino, поэтому предполагаю, что это не так уж трудно понять. Спасибо.

, 👍0

Обсуждение

Если (digitalRead(pir) == LOW), то вы приказываете сервоприводу перейти на 180 с помощью этой строки: for (pos = 180; pos >= 0; pos -= 1), @Dave X

Я бы запустил ваш код через "Инструменты" / "Автоматический формат" в IDE, что вы должны сделать перед публикацией в будущем, для здравомыслия ваших читателей, если не для вашего собственного., @timemage

Ладно, спасибо за подсказку, ребята !!, @Nathan Ghali


1 ответ


2

Не устанавливайте pos на 180 в ветви (digitalRead(pir) == LOW), если вы не хотите, чтобы он многократно подскакивал до 180 до тех пор, пока условие истинно.

void loop() {
  if (digitalRead(pir) == HIGH)
     pos = 180;
  myservo.write(pos);              // скажите сервоприводу перейти в позицию в переменной 'pos'
    
  Serial.print("Motion detected!");

  if (digitalRead(pir) == LOW)
    for (; pos > 0; pos -= 1) { // распад до 0 градусов
      myservo.write(pos);              // скажите сервоприводу перейти в позицию в переменной 'pos'
      delay(15);                       // ждет 15 мс, пока сервопривод достигнет нужного положения.
    }
    
  Serial.print("Motion ended!");
}

С другой стороны, вы можете использовать pos в качестве переменной состояния и упростить ситуацию:

void loop() {
  if (digitalRead(pir) == HIGH)
     pos = 180;
  elif (pos > 0 ){
     pos--;
     delay(15);
  }
  myservo.write(pos);
}
,

Если значение pir НИЗКОЕ, то управляемый скоростью код ОП будет снова и снова циклически переключаться между 180 и нулем., @Dave X

"до тех пор, пока условие истинно" или, может быть, "до тех пор, пока входные данные остаются НИЗКИМИ". Я собираюсь удалить свои предыдущие комментарии выше (и этот позже), потому что с вашими хорошими разъяснениями они будут выглядеть более несинхронизированными., @timemage

Я вставил код, работает как шарм, большое спасибо вам двоим, ребята !!, @Nathan Ghali

Похоже, вы должны "принять" этот ответ., @timemage