+1 голос

Всем доброго времени суток. Делаю проект на ардуино, нужна помощь. Задача такая: нужно чтобы при закрывании фоторезистора или выключении света светодиод включался на несколько секунд (5-10) и потом выключался. В общем получилось, но отсчет времени идёт от того момента, когда я убираю палец с фоторезистора, а должен идти со времени загорания светодиода. И ещё интервал времени до отключения бывает меняется (становится меньше). Вот что получилось:

int ledPin = 7;
int photoPin = A0;
int ledState = LOW;
long previousMillis = 0; 
long interval = 5000;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(photoPin, INPUT);

}

void loop() {
  if (analogRead (photoPin) >800)
  digitalWrite (ledPin, HIGH);
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis >= interval) {
  digitalWrite (ledPin, LOW);
  previousMillis = currentMillis; 
  if (ledState == HIGH)
      ledState = LOW;
  digitalWrite(ledPin, ledState);
  }


}

(6 баллов) 1 4
Почему для этой задачи просто не использовать delay() ?
На данном портале не приветствуется вопросы чисто по программированию.
На данном портале не приветствуется нарушение правил ред. политики. Её можно посмотреть в подвале сайта (https://breadboard.ru/content-policy). Данный вопрос их не нарушает, так что всё нормально.
Спасибо вам всем за помощь. Но я забыл дополнить. Светодиод должен гаснуть если я не убрал палец с фоторезистора. Т.е. я закрываю фоторезистор и через 5 секунд светодиод гаснет. Все эти пять секунд светодиод должен быть закрыт.
Спасибо всем большое за помощь)

5 Ответы

+4 голосов
 
Лучший ответ

Если автор вопроса больше ничего не забыл, то можно сделать так

int ledPin = 7;
int photoPin = A0;
long previousMillis = 0;
long interval = 5000;
unsigned long currentMillis;
long prevMillis;
int start = 0;
int led = 1;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(photoPin, INPUT);
}

void loop() {
  // Serial.println(analogRead (photoPin));
  if (analogRead (photoPin) > 800 && led == 1) {
    start = 1;
    previousMillis = millis();
    prevMillis = previousMillis;
    led = 0;
    digitalWrite (ledPin, HIGH);
    Serial.print("start "); Serial.println(millis());
  }

  if (start == 1)    currentMillis = millis();
  if (currentMillis - previousMillis >= interval  ) {
    previousMillis = millis();
    Serial.print("stop "); Serial.print(millis()); Serial.print(" "); Serial.println(previousMillis - prevMillis);
    digitalWrite (ledPin, LOW);
    start = 0;
    led = 0;
  }
  if (analogRead (photoPin) < 800) led = 1;
}

(221 баллов) 4 16
исправил
Спасибо огромное.) Заработало!
@Chester. Если вы считаете, что это лучший ответ, будет отлично если вы его примете, нажав на зелёную галочку. Так вы явно обозначите лучшее решение, для тех кто будет смотреть вопрос позже, а также добавите баллов репутации себе и автору ответа.
У меня снова вопрос. А вы не знаете с чем связано то, что светодиод гаснет через разные промежутки времени? Если интервал стоит 5 секунд то светодиод может погаснуть и через меньшее временя.
Вы это как определяете? На глаз? Вставьте в код между if-ами вывод в сериал, например так
Serial.print(currentMillis - previousMillis); Serial.print("  ");Serial.println(digitalRead(ledPin));
и посмотрите через какие интервалы времени значение меняется с 1 на 0.
Там сильная разница (1-2 секунды). На глаз видно.
Да, действительно был косяк. Вот, исправил код и добавил вывод в монитор порта
int ledPin = 7;
int photoPin = A0;
long previousMillis = 0;
long interval = 5000;
unsigned long currentMillis;
long prevMillis;
int start = 0;
int led = 1;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(photoPin, INPUT);
}

void loop() {
  // Serial.println(analogRead (photoPin));
  if (analogRead (photoPin) > 800 && led == 1) {
    start = 1;
    previousMillis = millis();
    prevMillis = previousMillis;
    led = 0;
    digitalWrite (ledPin, HIGH);
    Serial.print("start "); Serial.println(millis());
  }

  if (start == 1)    currentMillis = millis();
  if (currentMillis - previousMillis >= interval  ) {
    previousMillis = millis();
    Serial.print("stop "); Serial.print(millis()); Serial.print(" "); Serial.println(previousMillis - prevMillis);
    digitalWrite (ledPin, LOW);
    start = 0;
    led = 0;
  }
  if (analogRead (photoPin) < 800) led = 1;
}
Спасибо огромнейшее))) Вы очень меня выручили.
+5 голосов

Как уже сказал issaom, в данном случае логично использовать функцию delay(). Вот код с её использованием:

int ledPin = 7;
int photoPin = A0;
int ledState = LOW;
long interval = 5000;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(photoPin, INPUT);
  digitalWrite(ledPin, ledState);
}

void loop() {
  if (analogRead (photoPin) >800){
    digitalWrite (ledPin, HIGH);
    delay(interval);
    digitalWrite(ledPin, ledState);
  }
}

(917 баллов) 5 64 103
+3 голосов

В связи с новыми обстоятельствами  алгоритм программы должен быть следующим:

При понижении яркости запоминаем его в переменной типа unsigned long , и потом её сравниваем с текущем , но при повышении яркости выходим из ожидания. Можно это реализовать через цикл :

if(analogRead(ваш пин)>800){
//Запоминаем время
while ((millis()-memoryTime)<period && analogRead(ваш пин)<800){

}
}

(2.7 тыс. баллов) 7 17 38
+2 голосов

Попробуй так

int ledPin = 7;
int photoPin = A0;
int ledState = LOW;
long previousMillis = 0;
long interval = 5000;
unsigned long currentMillis;
int start = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(photoPin, INPUT);

}

void loop() {
  if (analogRead (photoPin) > 800) {
    start = 1;
    digitalWrite (ledPin, HIGH);
  }
  if (start == 1) currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    digitalWrite (ledPin, LOW);
    previousMillis = currentMillis;
    start = 0;
  }
}

(221 баллов) 4 16
+1 голос
Алгоритм должен быть таков

При понижении яркости запоминаем его в переменной типа unsigned long , и потом её сравниваем с текущем . Более одной переменной не нужно , остальные константы.
(2.7 тыс. баллов) 7 17 38
Добро пожаловать на Бредборд! Сайт вопросов и ответов на тему Arduino, Raspberry Pi и хоббийной электроники в целом. Цель Бредборда — быть максимально полезным. Поэтому мы строго следим за соблюдением правил, боремся с холиворами и оффтопиком.
  1. Aromik

    75 балл(ов)

  2. Un_ka

    54 балл(ов)

  3. parovoZZ

    12 балл(ов)

  4. sser

    10 балл(ов)

  5. Тёмик

    5 балл(ов)

  6. NesteruS

    5 балл(ов)

Награды месяца
1-е место: OLED-дисплей (Troyka-модуль)
2-е место: Графический экран 128×64
3-е место: Текстовый дисплей 16×2 (Troyka-модуль)

...