Таймер в коде

Тема в разделе "Arduino & Shields", создана пользователем Sergey_K, 14 мар 2020.

  1. Sergey_K

    Sergey_K Нерд

    Добрый день, уважаемые друзья.
    Никак не получается найти логику старта действия с задержкой.

    Что есть:

    1. Фоторезистор
    2. Реле со светом

    Что нужно

    1. Чтобы по данным от фоторезистора загорался свет.
    Это есть и все хорошо

    2. Чтобы свет гасился с 10 секундной (10000 милисек) задержкой по данным от фоторезистора.
    Здесь не все хорошо.

    То есть, если на секунде 9999 милисекундах резистор сообщит, что пора выключаться, то мы выключимся через 1 милисекунду, а не через 10000.

    Помогите, пожалуйста, советом или кодом или уже ранее пройденной темой.

    Код (C++):

    int svet=11;
    unsigned long timing;
    #define PERIOD 10000
    #define PIN_PHOTO_SENSOR A0

    void setup() {
    // put your setup code here, to run once:
    pinMode(svet, OUTPUT);
    Serial.begin(9600);

    }

    void loop() {

    int val = analogRead(PIN_PHOTO_SENSOR);
    Serial.println(val);


        if (val > 3)
        {
          if (millis() - timing >= PERIOD)
        {
          digitalWrite(svet, LOW);
          timing+=PERIOD;
        }
        }

         else
        {
         
           digitalWrite(svet, HIGH);
        }
        }
     
    Последнее редактирование: 15 мар 2020
  2. akl

    akl Гуру

    в момент засвечивания фоторезистора надо только засекать время, причем только один раз (для этого ввести переменную-флаг), а отключать свет уже отдельно по истечению времени
     
  3. Sergey_K

    Sergey_K Нерд

    Все верно.

    Почему-то не написал сам в теме, что хочу начинать отсчет времени именно от момента засвета.

    Вопрос стоит именно в реализации..
    Я весьма и весьма посредственный человек в написании кодов, что, вероятно, очевидно.
    Могу или чужое перепилить или пример разобрать, а сам как минимум синтаксиса не знаю.

    Булин вставить - это ок. А как с ним поступить дальше и как сделать счетчик засвета и почему один раз - это уже выше моего уровня понимания.
     
  4. a1000

    a1000 Гуру

    Ну во первых ваш скетч вообще не должен компилироваться. Что это у вас за мусор
    Код (C++):
    pinMode(svet1, OUTPUT);
    А если у вас проблемы программированием а задача ограничивается только действиями описанными в первом посту, сделайте тупо и не по феншую. Проверяете засвет фоторезистора, если есть - включаете светодиод потом задержка в 10 сек и гасите его.
    Так делать не хорошо, но в вашем случае работать будет.
     
  5. Sergey_K

    Sergey_K Нерд

    Это маленькая вырезка из большего скетча, чтобы другими вещами вас не грузить, я постарался вычистить всё, но эту строку упустил.

    Задержка в виде делея не прокатит. Если вы о нем, конечно. Есть другие части кода, которые по известным причинам будут так же отложены на 10 секунд.


    Я тут вот на что наткнулся. Только не понимаю на какую часть кода обратить внимание, чтобы экспроприировать. И вообще то ли это. КМК очень похоже, что да.

    http://forum.amperka.ru/threads/Срабатывание-таймера-только-после-выполнения-условий.11783/
     
  6. a1000

    a1000 Гуру

    Тогда да, надо делать через millis(). Но возникает дополнительный вопрос - что надо делать если фоторезистор по истечении 10 сек остаётся засвеченным? Свет нужно погасить на какой-то промежуток времени а потом опять включать, или ничего не гасить, а запустить новый отсчёт 10 секунд?
     
  7. Sergey_K

    Sergey_K Нерд

    Запустить новый отсчет.


    Вообще, это автоматический свет для велосипеда. То есть он смотрит на мир и оценивает светло или нет. и по этим данным включает свет.
    Проезжая под фонарем/фонарями, свет все же выключается. я хотел поставить задержку в минуту или больше на то, что бы он оставался включенным. но в жизни на реальном тесте это быстро показало насколько я не прав в коде. Изначально думал, что сам все сделаю, но эта часть меня убивает.
    Там еще поворотники в коде(на сенсорных кнопках), их я и вычистил. А) чтобы не заставлять всё то читать, Б) не позориться.
     
    Slaiterx нравится это.
  8. Slaiterx

    Slaiterx Гик

    поставь на велосипед такой датчик https://a.aliexpress.ru/_eLaPqY направь в низ а не в верх и отрегулируй переменным резистором ну и к нему на выход реле и все программировать не чего не надо
     
    Последнее редактирование: 15 мар 2020
  9. b707

    b707 Гуру

    Sergey_K, не пойму, в чем у вас проблема. Код ведь элементарный.
    Не знаю, какие значения идут с фотодатчика, когда "светло", а какие "темно", поэтому напишу в общем:

    Код (C++):
    unsigned long  last_dark_time;  // глобальная  или статическая переменная

    int val = analogRead(PIN_PHOTO_SENSOR);

    if ( "темно" )
        {
         digitalWrite(svet, HIGH); // включаем свет
         last_dark_time = millis();  // засекаем время
       }
    else  {   // если "светло"

          if (millis() -  last_dark_time >= PERIOD)  // если время истекло
        {
          digitalWrite(svet, LOW); // выключаем свет
         }
    }
     
    Tomasina нравится это.
  10. akl

    akl Гуру

    Код (C++):
    int svet=11;
    unsigned long timing;
    #define PERIOD 10000
    #define PIN_PHOTO_SENSOR A0
    char dayflag=0; //переменная-флаг
    void setup() {
    // put your setup code here, to run once:
    pinMode(svet, OUTPUT);
    Serial.begin(9600);

    }

    void loop() {

      int val = analogRead(PIN_PHOTO_SENSOR);
      Serial.println(val);

      if (val > 3) //если настал день
      {
        if(!dayflag)//флаг нулевой - значит до этого была ночь
        { //взводим флаг, теперь сюда не зайдет пока не
          dayflag=1;//пройдет через ночь
          timing=millis();//засекаем время для выключения света
        }
      }
      else //если настала ночь
      {
        dayflag=0; //сбрасываем флаг
        digitalWrite(svet, HIGH);
      }

      //если прошло время и флаг взведен - выключаем свет
      if (millis() - timing >= PERIOD && dayflag)
      {
        digitalWrite(svet, LOW);
      }
    }
    ничего не проверял, возможно будет работать неправильно, но по такой логике можно сделать чтоб работало

    ну или так как постом выше - без флага, а просто обнуляя счетчик каждый раз пока темно - так проще и возможно даже лучше
     
  11. Sergey_K

    Sergey_K Нерд

    Товарищи, большое вам спасибо.
    Оба варианта работают как надо

    это и это как раз и есть то, что для меня было не очевидно.

    Код (C++):

    digitalWrite(svet, HIGH);// включаем свет
         last_dark_time = millis();// засекаем время
     

    Код (C++):
       
    if(!dayflag)//флаг нулевой - значит до этого была ночь
       {//взводим флаг, теперь сюда не зайдет пока не
          dayflag=1;//пройдет через ночь
          timing=millis();//засекаем время для выключения света
       }
     
     
  12. Sergey_K

    Sergey_K Нерд

    Забавен тот факт, что именно от него я и хочу избавиться в схеме - он большой. мало того, с него я и выпаял фоторезистор :)
    этот датчик дает данные 1 или 0. в принципе особой разницы не вижу данные 1/0 или данные которые дает сам фоторезистор - 0-5=темно(по моим замерам) 6-1023(светло) опять же по моим замерам

    и у него моментальный вкл-выкл. то есть как дискотека. при любом внешнем источнике света (фары машин, фонари и т.д.), будь он хоть на микросекунду рядом.
     
    Последнее редактирование: 15 мар 2020
  13. Sergey_K

    Sergey_K Нерд

    Да.
    Я перенес все это добро на плату в easyEDA и если кому надо (в чем сомневаюсь),
    + есть визуально собранный проект с кодом и т.д. в тинкеркаде.

    пишите, пошарю