Нужна помощь с millis()

shemovoi
Offline
Зарегистрирован: 15.09.2013

Доброго времени суток, осваиваю ардуино. Суть вопроса такова, вот код

#define sensor 8
#define siren 13
int val;

void setup()
{
  pinMode(siren, OUTPUT);
  pinMode(sensor,INPUT);
  digitalWrite(siren,LOW);
}
void loop()

{
  val = digitalRead(sensor);
  if(val >=1)
{
  
  digitalWrite(siren,HIGH);
  delay(10000);
  digitalWrite(siren,LOW);
} 
}

Это система аварийного выключения водоснабжения. Мне нужно, избавится от delay(). Избавится таким оброзом, чтобы сирена включалась на 5 минут и в это время МК совершал прочие действия и т.д. То есть, мне нужно использовать millis(), но как это сделать, чтобы МК выполнял действия  до тревоги и после нее я не пойму пока. Да, я вникал в туториал по миганию диодом с millis() но ни чего так и не понял, прошу помощи. Спасибо всем, кто пишет чтобы помоч.

keefa
Offline
Зарегистрирован: 19.06.2015

shemovoi пишет:

Доброго времени суток, осваиваю ардуино. Суть вопроса такова, вот код

#define sensor 8
#define siren 13
int val;

void setup()
{
  pinMode(siren, OUTPUT);
  pinMode(sensor,INPUT);
  digitalWrite(siren,LOW);
}
void loop()

{
  val = digitalRead(sensor);
  if(val >=1)
{
  
  digitalWrite(siren,HIGH);
  delay(10000);
  digitalWrite(siren,LOW);
} 
}

Это система аварийного выключения водоснабжения. Мне нужно, избавится от delay(). Избавится таким оброзом, чтобы сирена включалась на 5 минут и в это время МК совершал прочие действия и т.д. То есть, мне нужно использовать millis(), но как это сделать, чтобы МК выполнял действия  до тревоги и после нее я не пойму пока. Да, я вникал в туториал по миганию диодом с millis() но ни чего так и не понял, прошу помощи. Спасибо всем, кто пишет чтобы помоч.

#define sensor 8
#define siren 13
int val;
unsigned long lastMillis = millis();
boolean flag = 0;

void setup()
{
  pinMode(siren, OUTPUT);
  pinMode(sensor, INPUT);
  digitalWrite(siren, LOW);
}
void loop()

{
  val = digitalRead(sensor);
  if (val >= 1 && flag == 0)
  {
    digitalWrite(siren, HIGH);
    lastMillis = millis();
    flag = 1;
  }
  if (millis() - lastMillis >= 10000) {
    digitalWrite(siren, LOW);
    flag = 0;
  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я бы строку 23 кода keefa записал бы так

if (flag == 1 && millis() - lastMillis >= 10000) {

keefa
Offline
Зарегистрирован: 19.06.2015

ЕвгенийП пишет:

Я бы строку 23 кода keefa записал бы так

if (flag == 1 && millis() - lastMillis >= 10000) {

Согласен, так не придется дергать каждый цикл  digitalWrite(siren, LOW);
bwn
Offline
Зарегистрирован: 25.08.2014

А я бы отдал должное Лешаку.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

А я и отдал .. в смысле заценил и вставил в свою либу готовый макрос .. даже 2шт: на базе millis() для работы с миллисекундами и на базе ovf_count для снижения затрат на него. В ряде применений ещё и параметры "времени в миллисекундах" укоротил до 2-х байт (uint16_t вместо unsigned long), что позволяет сократить каждое обращение к функциям времени на 6 байт кода. :)

Обсуждение либы, свистки про ошибки принимаются тут: http://arduino.ru/forum/programmirovanie/arduino-kak-konechnyi-avtomat-zaodno-umenshaem-sketchi

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013
#define SENSOR_PIN      8
#define SIREN_PIN       13
#define SIREN_TIMEOUT   (10000 <= millis() - sirenStartTime)
#define ALARM           (digitalRead(SENSOR_PIN))
#define ON              HIGH
#define OFF             LOW

unsigned long sirenStartTime;

void setup()
{
  pinMode(SIREN_PIN, OUTPUT);
  pinMode(SENSOR_PIN, INPUT);
  digitalWrite(SIREN_PIN, LOW);
}


void loop()
{
  if (ALARM) siren(ON);
  if (SIREN_TIMEOUT) siren(OFF);
}


void siren(boolean state)
{
  if (state == ON) sirenStartTime = millis();
  digitalWrite(SIREN_PIN, state);
}

Так же нагляднее, особенно когда код сильно разрастется ;)

shemovoi
Offline
Зарегистрирован: 15.09.2013
Спасибо за ответ и помощь, но я яхочу понять, как все это работает, а не просто получить готовый код как халявщик какой-то) Я написал комментарии к коду и если не сложно прошу объяснить, что происходит в непонятных мне строках и исправить если нужно. Спасибо.#define sensor 8                     //Пин сенсора 8
#define siren 13                     // Пин сирены 13
int val; 
unsigned long lastMillis = millis(); // ВОТ ЭТО НУЖНО ОБЪЯСНИТЬ
boolean flag = 0;
 
void setup()
{
  pinMode(siren, OUTPUT);
  pinMode(sensor, INPUT);
  digitalWrite(siren, LOW);
}
void loop()
 
{
  val = digitalRead(sensor);          // Считываем значение и записываем в переменную val
  if (val >= 1 && flag == 0)          // если val больше или равно И flag равно нулю
  {
    digitalWrite(siren, HIGH);        // Включаем сирену
    lastMillis = millis();            // НУЖНО ОБЪЯСНИТЬ, ЧТО ЗДЕСЬ ПРОИСХОДИТ
    flag = 1;                         // Записываем в flag еденицу
  }
if (flag == 1 && millis() - lastMillis >= 10000)// НУЖНО ОБЪЯСНИТЬ, ЧТО ЗДЕСЬ ПРОИСХОДИТ
  {
    digitalWrite(siren, LOW);         // Выключаем сирену
    flag = 0;                         // Записываем ноль в flag
  }
}

 

keefa
Offline
Зарегистрирован: 19.06.2015
Спасибо за ответ и помощь, но я яхочу понять, как все это работает, 
а не просто получить готовый код как халявщик какой-то) 
Я написал комментарии к коду и если не сложно прошу объяснить, 
что происходит в непонятных мне строках и исправить если нужно. Спасибо.
#define sensor 8                     //Пин сенсора 8
#define siren 13                     // Пин сирены 13
int val; 
unsigned long lastMillis = millis(); // ВОТ ЭТО НУЖНО ОБЪЯСНИТЬ// объявляем переменную длинную без знака
// в данном случае присваиваем значение millis();(http://arduino.ru/Reference/Millis). но эт не обязательно,
// можно просто присвоить 0.
boolean flag = 0; 
 
void setup()
{
  pinMode(siren, OUTPUT);
  pinMode(sensor, INPUT);
  digitalWrite(siren, LOW);
}
void loop()
 
{
  val = digitalRead(sensor);          // Считываем значение и записываем в переменную val
  if (val >= 1 && flag == 0)          // если val больше или равно И flag равно нулю
  {
    digitalWrite(siren, HIGH);        // Включаем сирену
    lastMillis = millis();            // НУЖНО ОБЪЯСНИТЬ, ЧТО ЗДЕСЬ ПРОИСХОДИТ // здесь мы фиксируем время
    // от которого начинаем отсчитывать время. тоесть от момента нажатия кнопки
    flag = 1;                         // Записываем в flag еденицу
  }
if (flag == 1 && millis() - lastMillis >= 10000)// НУЖНО ОБЪЯСНИТЬ, ЧТО ЗДЕСЬ ПРОИСХОДИТ// проверяем - 
// равен ли флаг единице и проверяем прошло ли 10000 мСек от нажатия кнопки. если оба уловия совпадают
// то выполняем функцию следующую за условием, если нет то пропускаем, ждем пока условие не совпадет.
// 
  {
    digitalWrite(siren, LOW);         // Выключаем сирену
    flag = 0;                         // Записываем ноль в flag
  }
}

ответ в теле кода

shemovoi
Offline
Зарегистрирован: 15.09.2013

Очень блогадарен за помощь)

keefa
Offline
Зарегистрирован: 19.06.2015

shemovoi пишет:

Очень блогадарен за помощь)

Всегда рад помочь. Надеюсь что понятно объяснил.

saftik
Offline
Зарегистрирован: 08.04.2015

Tomasina пишет:

#define SENSOR_PIN      8
#define SIREN_PIN       13
#define SIREN_TIMEOUT   (10000 <= millis() - sirenStartTime)
#define ALARM           (digitalRead(SENSOR_PIN))
#define ON              HIGH
#define OFF             LOW

unsigned long sirenStartTime;

void setup()
{
  pinMode(SIREN_PIN, OUTPUT);
  pinMode(SENSOR_PIN, INPUT);
  digitalWrite(SIREN_PIN, LOW);
}


void loop()
{
  if (ALARM) siren(ON);
  if (SIREN_TIMEOUT) siren(OFF);
}


void siren(boolean state)
{
  if (state == ON) sirenStartTime = millis();
  digitalWrite(SIREN_PIN, state);
}

Так же нагляднее, особенно когда код сильно разрастется ;)

круто , не знал что в defaine можно подставлять уравнения
не могли бы вы пояснить как работает 20 строчка кода. не должно ли быть после (ALARM)  например == HIGH  или == LOW (в зависимости от сенсора)

и как у нас идет обращение к void siren

не нужно ли в loop добавить siren();

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

#define имя заменить_так_то

работает до компилятора. Это препроцессор. Он тупо делает подстановки текстов лексем и может проверять то что получилось на наличие подстановок ещё, спускаясь вглубь сколь угодно глубоко, но без рекурсий. Обеспечивается это тем, что каждый #define умеет находить только те подстановки, которые были текстуально определены до него конкретно.

В данном случае, происходит преобразование текста до компиляции в такой:

unsigned long sirenStartTime;
	 
void setup()
{
  pinMode(13, 1);
  pinMode(8, 0);
  digitalWrite(13, 0);
}


void loop()
{
  if ( (digitalRead(8)) ) siren(1); // помним что 0 это false остальное true
  if ( (10000 <= millis() - sirenStartTime) ) siren(0);
}

void siren(boolean state)
{
  if (state == 1) sirenStartTime = millis();
  digitalWrite(13, state);
}

Это, что увидит комплятор. avg-gcc запущенный с ключом -E выдаст примерно такое.

saftik
Offline
Зарегистрирован: 08.04.2015

Arhat109-2
спасибо что ответили,
то что дефайн подставляет до компиляции это я понимал.  не знал только что можно такие уровнения подставлять

мне все равно непонятно , теперь уже 13 строка ((

в " if" ведь должно быть условие. 
например 14 строку я понимаю так  

if ( (10000 <= millis() - sirenStartTime) ) siren(0);

если отработали 10 сек. то сирену выключить (поставить в ноль, LOW, false)
то есть тут у нас явное условие "прошло ли 10 сек.?"

а вот строку  13 вашего последнего поста понимаю так.

 if ( (digitalRead(8)) )  siren(1); 

если МОЖЕМ ПРОЧИТАТЬ pin8, то siren будет true.
получается что тут "условие" это сама возможность прочитать пин8,  но ведь мы всегда его можем прочитать.

не должно ли быть что -то типо этого
if ( digitalRead(8) == HIGH)  siren=1;  }

если мы прочитали pin8 и ОН РАВЕН high  то siren будет равен одному (включится)
тут "условие" pin8 ==HIGH?  

тоесть я виду к тому, что в вашем варианте нет явного условия при котором siren станет true 

простите что задаю глупые вопросы.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

про #define уже написали, все верно, просто тупая замена синонима на его содержимое. Именно что тупая, без проверки на корректность, поэтому длинные выражения всегда должны быть в скобках, чтобы сохранить задуманный порядок действий.

Для компилятора выражение if(...) всегда возвращает только два состояния: true если содержимое скобок истинно и false если ложно. Поэтому if (ALARM) развернется до if (digitalRead(8)), и выражение читается ЕСЛИ СОСТОЯНИЕ ПИНА 8 , далее по-любому будет либо true, либо false, поэтому если ожидается TRUE, собственно само равенство ==TRUE можно не писать. Если ожидается FALSE, то можно просто написать через инверсию: if (!ALARM) ...
Короче, выражения if (digitalRead(8) == HIGH) и if (digitalRead(8)) полностью равноценны, писать можно и так и так, для наглядности в строках 20 и 27 они написаны по-разному.

>и как у нас идет обращение к void siren. не нужно ли в loop добавить siren();
не нужно. Обращение идёт после проверки if, допустим, если true, то обращаемся к функции siren и передаем ей параметр ON, который является синонимом TRUE, который равен 1. Эта единичка присваивается локальной (внутренней) переменной state и дальше новое сравнение if.

Строка (millis() - sirenStartTime >= 10000) у меня просто зеркально перевернута: (10000 <= millis() - sirenStartTime) для удобства, чтобы в блоке define все цифры были слева, так их визуально быстрее найти.
Таким образом, если я через год захочу поменять какой-то параметр, мне не придется тратить десятки минут и шарить по всему коду, чтобы вспомнить как оно работает и какой пин или цифру надо поменять, а просто исправить заданные уставки, что займёт секунды, потому что все это вынесено в самое начало. И за счет использраания синонимов #define сама логика основного цикла через год так же легко прочитается, без вникания в детали:
{
ЕСЛИ ТРЕВОГА, ТО СИРЕНУ ВКЛЮЧИТЬ
ЕСЛИ СИРЕНА ОРЕТ ДОЛГО, ТО СИРЕНУ ВЫКЛЮЧИТЬ
}

Клапауций 911
Offline
Зарегистрирован: 18.10.2015

Tomasina пишет:
{ ЕСЛИ ТРЕВОГА, ТО СИРЕНУ ВКЛЮЧИТЬ ЕСЛИ СИРЕНА ОРЕТ ДОЛГО, ТО МАШИНУ СЖЕЧЬ, ВНИМАТЕЛЬНО ВЫСЛУШАТЬ ХОЗЯИНА И ПОДАРИТЬ ОГНЕТУШИТЕЛЬ}

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

...то найти другого хозяина.

Клапауций 911
Offline
Зарегистрирован: 18.10.2015

Tomasina пишет:
...то найти другого хозяина.

сгоревший автомобиль ищет умного хозяина

saftik
Offline
Зарегистрирован: 08.04.2015

 Tomasina спасибо за то что все объяснили .

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

saftik пишет:

в " if" ведь должно быть условие. 

Увы, это от недостатка образования.

У нас посему-то научить программировать пытаются прежде, чем прочитан курс булевой алгебры. А булева алгебра, пожалуй, для программирования поважнее, чем арифметика.

Собственно, в "if" должно быть не условие, а логическое (булево) выражение.

А в языках C/C++ традиционно считается, что "0" - это "false", а все, что не равно нулю - "true".

Tomasina пишет:

... Короче, выражения if (digitalRead(8) == HIGH) и if (digitalRead(8)) полностью равноценны

Отнюдь.

В используемых терминах полностью равноценны if (digitalRead(8) != LOW) и if (digitalRead(8)).

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

andriano пишет:
Отнюдь. В используемых терминах полностью равноценны if (digitalRead(8) != LOW) и if (digitalRead(8)).

Истинно так. Опередили. :)

saftik
Offline
Зарегистрирован: 08.04.2015

Что страшного в том что я назвал " логическое (булево) выражение" - " условием"?
я не программист и не знаю тонкостей и правильных названий,  люди меня поняли а я понял их думаю этого достаточно,
 То что я не достаточно хорошо разбираюсь в программировании не говорит о том что у меня недостаток образования,
я специалист в другой сфере, а arduino это хобби.

не думаю что вы такой на все руки мастер,
Уверен что если вас попросить приготовить какое-то блюдо скажем из французской или скажем из сербской кухни , вы его правильно приготовите .

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

P.S .    получаеться что здесь http://arduino.ru/Reference/If нас всех обманывают . написанно именно условие а не "логическое (булево) выражение

Клапауций 911
Offline
Зарегистрирован: 18.10.2015

saftik пишет:

Что страшного в том что я назвал " логическое (булево) выражение" - " условием"?

ничего страшного - тебя просто съест рептилоид.

keefa
Offline
Зарегистрирован: 19.06.2015

saftik пишет:

Уверен что если вас попросить приготовить какое-то блюдо скажем из французской или скажем из сербской кухни , вы его правильно приготовите .

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

saftik пишет:

Что страшного в том что я назвал " логическое (булево) выражение" - " условием"?
я не программист и не знаю тонкостей и правильных названий,  люди меня поняли а я понял их думаю этого достаточно,
 То что я не достаточно хорошо разбираюсь в программировании не говорит о том что у меня недостаток образования,
я специалист в другой сфере, а arduino это хобби.

А что страшного в том, если кто-то плохо разбирающийся в кулинарии приготовит что-то несъедобное?

Если бы Вы внимательно прочитали мое сообщение, поняли бы, что недостаток образования ни у одного Вас. Это вообще характерно для начинающих программистов.

Как бы Вы посмотрели на человека, который пытается программировать, ни при этом не имеет поняия об арифметических операциях?

А с булевой алгеброй именно так и происходит.

И, собственно, я писл не для того, чтобы Вас обидеть, а для того, чтобы подсказать Вам, чего Вам не хватает, на что следовало бы обратить внимание, если Вы хотите программировать.

Цитата:

P.S .    получаеться что здесь http://arduino.ru/Reference/If нас всех обманывают . написанно именно условие а не "логическое (булево) выражение

Именно так.

У того, кто это писал, тоже наблюдается недостаток образования.

Что как раз подтверждает мои слова.