Задержка включения и выключения вентиляции в санузле

Tayfun
Offline
Зарегистрирован: 02.11.2016

Доброго времени суток, уважаемые форумчане! Как новичок, прошу помощи у гуру в моем первом проекте. Хочу сделать таймер (на базе ардуино) задержки включения и выключения вентилятора в санузле.

Имеем: 1)Ардуино; 2)фоторезистор 3) резистор 10кОм; 4) релейный модуль

Алгоритм следующий: 1) Включаем свет; 2) вентилятор не включается 2мин.; 3)если свет горит более 2 мин., то включается вентилятор и работает пока горит свет и после отключения света продолжает работать еще 5 мин.; 4) если свет горит менее 2 мин., то вентилятор не включается.

Написал скетч (для отладки время принял 10 и 15сек.) :



[code]
}

void loop()
{
digitalWrite(Rele, HIGH);
if (analogRead(ldr) < 800) //если свет включен
{
goto A; //то идем на А 
}
else goto B; //иначе идем на В 
A: delay(10000); // выдерживаем паузу 
if (analogRead(ldr) < 800) //после паузы проверяем включен ли свет 
{
 while (analogRead(ldr) < 800) //если включен свет, то пока свет горит 
digitalWrite(Rele, LOW); //реле включено
}
else goto B; //иначе идем на В 
  delay(15000); //после выключения света выдерживаем паузу и выключаем реле 
B: digitalWrite(Rele, HIGH); //реле выключено
}

[/code]

В итоге имеем: при включении ардуино срабатывает реле и через 10сек выключается, при засвете фоторезистора в течение 15сек - реле включается и выключается по истечении 10сек. При  засвете фоторезистора в течение 1сек - реле также включается и выключается по истечении 10сек. Короче все получается наоборот. Не могу понять где косяк. Помогите плиз!

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

Вы уверены, что у Вас реле включается по LOW, а не по HIGH? Схему покажите.

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

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

Вы уверены, что у Вас реле включается по LOW, а не по HIGH? Схему покажите.

+++

Tayfun
Offline
Зарегистрирован: 02.11.2016

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015
void loop()
{
    digitalWrite(Rele, HIGH);
    
    if (analogRead(ldr) < 800) //если свет включен
    {
        goto A; //то идем на А 
    }
    else 
    {
        goto B; //иначе идем на В 
    }
    
    A: delay(10000); // выдерживаем паузу 
    
    if (analogRead(ldr) < 800) //после паузы проверяем включен ли свет 
    {
        while (analogRead(ldr) < 800) //если включен свет, то пока свет горит 
        {
            digitalWrite(Rele, LOW); //реле включено
        }
    }
    else 
    {
      goto B; //иначе идем на В 
    }
    
    delay(15000); //после выключения света выдерживаем паузу и выключаем реле 
    
    B: digitalWrite(Rele, HIGH); //реле выключено
}

Специально раскидал код - тут гдето есть включение?

Только выключение каждые перу миллисекунд и перепроверка...

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

int Rele = 13;
int ldr = A0;

void setup()
{
    pinMode(Rele, OUTPUT);
    digitalWrite(Rele, HIGH);
}

void loop()
{
    
    
    if (analogRead(ldr) < 800) //если свет включен
    {
        digitalWrite(Rele, LOW); //реле включено
        delay(10000); // выдерживаем паузу 
        
    }
    else 
    {
        digitalWrite(Rele, HIGH); //реле выключено
         delay(10000); // выдерживаем паузу 
    }
    
}

Помоему так лучше и проще....

Tayfun
Offline
Зарегистрирован: 02.11.2016

Строка 20 -включение реле

 

Tayfun
Offline
Зарегистрирован: 02.11.2016

Сейчас попробую

 

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

Tayfun пишет:

Строка 20 -включение реле

 

а смысл постоянно выключать?? в его коде на 6 строке!

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

Ответа на вопрос нет. Я не знаю, что у Вас там за модуль, а схему Вы не дали.

Просто проверьте как у Вас включается реле. ЧТо нужно на него подать, чтобы оно включилось HIGH или LOW. Понимаете как это проверить?

Tayfun
Offline
Зарегистрирован: 02.11.2016

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

Ответа на вопрос нет. Я не знаю, что у Вас там за модуль, а схему Вы не дали.

Просто проверьте как у Вас включается реле. ЧТо нужно на него подать, чтобы оно включилось HIGH или LOW. Понимаете как это проверить?

[code]
int Rele = 13;


void setup()
{
    pinMode(Rele, OUTPUT);
    digitalWrite(Rele, HIGH);
}

void loop()
{
    
    
   
        digitalWrite(Rele, LOW); //реле включено
     
        
  
    
}

[/code]

Так?

Tayfun
Offline
Зарегистрирован: 02.11.2016

p.masyukov,  Попробовал Ваш код. Все равно какая-то ерунда получается. Вначале вроде нормально было, а потом то через 3сек включится, то через 6сек выключится

 

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

Tayfun пишет:

p.masyukov,  Попробовал Ваш код. Все равно какая-то ерунда получается. Вначале вроде нормально было, а потом то через 3сек включится, то через 6сек выключится

 

не. по коду всё там правильно. 

он не делает всё то что ждете от него... он для проверки реле!!!!

а если вам надо тот алгоритм что описан --- то Вам его тут никто не напишет (он конечно не сложный, так мелочи) - вам в рездел ищу исполнителя!!!

один из них я..

Tayfun
Offline
Зарегистрирован: 02.11.2016

Исправил код

[code]
#define Rele 13 //переменная с номером пина реле
#define ldr  0 //и фоторезистора


void setup() {

pinMode(Rele, OUTPUT); //указываем, что реле - выход
pinMode(ldr, INPUT); //указываем, что фоторезистор - вход

}

void loop()
{
digitalWrite(Rele, LOW);
if (analogRead(ldr) > 800) //если свет включен
{
goto A; //то идем на А 
}
else goto B; //иначе идем на В 
A: delay(10000); // выдерживаем паузу 
if (analogRead(ldr) > 800) //после паузы проверяем включен ли свет 
{
 while (analogRead(ldr) > 800) //если включен свет, то пока свет горит 
digitalWrite(Rele, HIGH); //реле включено
}
else goto B; //иначе идем на В 
  delay(15000); //после выключения света выдерживаем паузу и выключаем реле 
B: digitalWrite(Rele, LOW); //реле выключено
}


[/code]

1) Да, действительно релейный модуль включается у меня по HIGH;

2)В строках, где analogRead(ldr)<800 был неправильный знак - исправил на analogRead(ldr)>800

Проверил - вроде работает! Спасибо всем за помощь!

Подскажите еще, если нетрудно, как это можно реализовать без delay. Хочу поставить еще одно реле и фоторезистор, чтобы туалет и ванна включались независимо друг от друга.

p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015
Tayfun
Offline
Зарегистрирован: 02.11.2016

Спасибо, Павел за ссылки! А по поводу...

p.masyukov пишет:

а если вам надо тот алгоритм что описан --- то Вам его тут никто не напишет (он конечно не сложный, так мелочи) - вам в рездел ищу исполнителя!!!

один из них я..

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

30andrew
Offline
Зарегистрирован: 17.11.2018

Павел, от меня тоже спасибо за участие в теме и разъяснения. Поскольку я еще более "начинающий, чем Tayfun, то задам Вам вопрос от себя - если можете, то посоветуйте, как скорректировать код, чтобы ограничить максимальное время работы вентилятора заданным временем, например 20 минут. Просто иногда забывают выключить свет в туалете :).

Спасибо.

 

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

30andrew пишет:

...скорректировать код, чтобы ограничить максимальное время работы вентилятора заданным временем, например 20 минут. Просто иногда забывают выключить свет в туалете :).

Это - не решение проблемы. Решение - автоматически выключать свет.

30andrew
Offline
Зарегистрирован: 17.11.2018

Соглашусь, но при условии, что будет абсолютная уверенность, что свет именно забыли выключить. Допускаю  такое решение, но если задержка выключения будет увеличена до, допустим, 1-2х часов, а если понадобится восстановить после отключения свет - то можно и перещелкнуть клавишей включения света. В моем случае такое решение не подходит, т.к. оно трудно реализуемо: надо прокладывать провода к светильнику, что испортит интерьер, да и по технике безопасности не айс. Опять же надо будет встраивать куда-то симистор или реле с проводами управления и т.д. и т.п. Хлопотно это.  Ремонт из-за этого точно делать не буду. Можно и задержкой на отключение ограничиться.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вообще то это все можно реализовать .... через автоматы Пуха.

Эта версия просто по свету вкл /выкл вентилятор

/**/
const byte FotoPin =/*пин*/A0;
const byte FunPin =/*пин*/2;
enum state_t {FunOFF = 0, FunON} state;
void stand(state_t s) {
  state = s;
  switch (state) {
    case FunOFF:
      digitalWrite(FunPin, HIGH); //вентилятор выключен
      break;
    case FunON:
      digitalWrite(FunPin, LOW); //вентилятор  включен
      break;
  }
}
//---------------------------
void setup() {
  pinMode(FunPin, OUTPUT);
  stand(FunOFF);
}

void loop() {
  int foto = analogRead(FotoPin);
  switch (state) {
    case FunOFF:
      /*если свет включен то включить вентилятор */
      if (foto < 800) stand(FunON);
      break;
    case FunON:
      /*если свет выключен то выключить вентилятор */
      if (foto > 800) stand(FunOFF);
      break;
  }
}

А вот это включает с задержкой как у ТС

/**/
const byte FotoPin =/*пин*/A0;
const byte FunPin =/*пин*/2;
enum state_t {FunOFF = 0, FunON} state;
unsigned long past;
const unsigned long time10s = 10000;
const unsigned long time15s = 15000;
void stand(state_t s) {
  state = s;
  switch (state) {
    case FunOFF:
      digitalWrite(FunPin, HIGH); //вентилятор выключен
      break;
    case FunON:
      digitalWrite(FunPin, LOW); //вентилятор  включен
      break;
  }
}
//---------------------------
void setup() {
  pinMode(FunPin, OUTPUT);
  stand(FunOFF);
}

void loop() {
  unsigned long mill = millis();
  int foto = analogRead(FotoPin);
  switch (state) {
    case FunOFF:
      if (foto > 800) past = mill;
      /*если свет включен то включить вентилятор */
      else if (mill - past >= time10s) stand(FunON);
      break;
    case FunON:
      if (foto < 800) past = mill;
      /*если свет выключен долго то выключить вентилятор */
      if (mill - past >= time15s) stand(FunOFF);
      break;
  }
}

ПС: Плохая новость в том что код не проверял

30andrew
Offline
Зарегистрирован: 17.11.2018

qwone пишет:

ПС: Плохая новость в том что код не проверял

Все равно спасибо. Завтра сам попробую проверить. Будет над чем подумать - я же новичек в программировании.

30andrew
Offline
Зарегистрирован: 17.11.2018

Пока с кнопками придется пробовать, т.к фотодатчики еще не купил. Кстати! Их 2 типа на Али есть - с фотодиодом и фотрорезистором.

Насколько понял, с фотодиодом дискретный датчик, а с фоторезистором - аналоговый. Кто-нибудь подскажет: это так или нет?

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

Это не так: возможны все 4 варианта сочетания типа датчика и типа выходного сигнала.

ku-ku
Offline
Зарегистрирован: 14.11.2018

30andrew пишет:

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

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

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

Касательно включения в случае автоматического выключения - так есть же давно выдуманный "проходной выключатель", если сильно нужно! Не подскажу как его задействовать именно в твоей конфигурации, но мож кому-то и поможет!

30andrew
Offline
Зарегистрирован: 17.11.2018

Я имел ввиду свойства датчика, а не платы Ардуино.

Поискал инструкции и нашел вот что:

- для датчика на фоторезисторе -

  • Компаратор чип LM393, он устойчив.

  • Может распознавать яркость и интенсивность света

  • Точность регулируемый

  • Рабочее напряжение 3,3 В-5 В

  • Выход: делаем цифровой коммутатор выход s (0 и 1) АО аналоговый выход напряжения

  • - для датчика на фотодиоде -

  • 1. Яркость окружающей среды и интенсивность света могут быть обнаружены (сравните с фоторезистором, направленность относительно хорошая, может воспринимать фиксированное направление источника света)
    2. Регулировка чувствительности синего цифрового потенциометра (рисунок)
    3. Рабочее напряжение 3,3 В-5 В
    4. Цифровые импульсные выходы (0 и 1)

  • Делаю вывод: фоторезисторный датчик - аналоговый, а фотодиодный - дискретный с регулировкой чувствительности

SLKH
Offline
Зарегистрирован: 17.08.2015

Tayfun пишет:

Исправил код

[code]
#define Rele 13 //переменная с номером пина реле
#define ldr  0 //и фоторезистора
[/code]

1) Да, действительно релейный модуль включается у меня по HIGH;

программа будет смотреться яснее, если прописать в начале

#define relayPin 13
#define ldrPin A0 
#define relayON digitalWrite(relayPin, HIGH)
#define relayOFF digitalWrite(relayPin, LOW)
 
и дальше по тексту оперировать этими определениями.

 

// исправлены ошибки 11:21.

 

 

30andrew
Offline
Зарегистрирован: 17.11.2018

qwone пишет:

ПС: Плохая новость в том что код не проверял

Проверил код. Компилятор выругался. Попробовал разобраться, но пока не получилось. Ругаться начинат уже с 8 строки. (имею ввиду вторую версию программы). Пишет error: 'state_t' was not declared in this scope и далее в таком же духе.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

30andrew пишет:
Проверил код. Компилятор выругался. Попробовал разобраться, но пока не получилось. Ругаться начинат уже с 8 строки. (имею ввиду вторую версию программы). Пишет error: 'state_t' was not declared in this scope и далее в таком же духе.
Если вы про это

/**/
const byte FotoPin =/*пин*/A0;
const byte FunPin =/*пин*/2;
enum state_t {FunOFF = 0, FunON} state;
unsigned long past;
const unsigned long time10s = 10000;
const unsigned long time15s = 15000;
void stand(state_t s) {
  state = s;
  switch (state) {
    case FunOFF:
      digitalWrite(FunPin, HIGH); //вентилятор выключен
      break;
    case FunON:
      digitalWrite(FunPin, LOW); //вентилятор  включен
      break;
  }
}
//---------------------------
void setup() {
  pinMode(FunPin, OUTPUT);
  stand(FunOFF);
}

void loop() {
  unsigned long mill = millis();
  int foto = analogRead(FotoPin);
  switch (state) {
    case FunOFF:
      if (foto > 800) past = mill;
      /*если свет включен то включить вентилятор */
      else if (mill - past >= time10s) stand(FunON);
      break;
    case FunON:
      if (foto < 800) past = mill;
      /*если свет выключен долго то выключить вентилятор */
      if (mill - past >= time15s) stand(FunOFF);
      break;
  }
}
/*Скетч использует 964 байт (3%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт.
*/

То у меня это компилируется. А если у вас не поддерживаются enum, то это же не моя вина.

http://cppstudio.com/post/8106/

30andrew
Offline
Зарегистрирован: 17.11.2018

Извините, если что не так! К сожалению, я пока на уровне чайника в С++.  Прежде чем написать про ошибку, я про enum почитал, пока код разбирал. Кстати, разобрался почти во всем, и не мог понять, в чем дело. Спасибо, это хороший пример решения задачи. У меня были совсем другие варианты в планах. Ваше решение мне показалось элегантней. А что надо сделать, чтобы компилятор enum понимал? Может апгрейд какой-то сделать? - У меня стандартная Ардуиновская программа версии 1.8.7

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Посто заменить переменной. Хватит bool или byte . Ну в общем так.

/**/
const byte FotoPin =/*пин*/A0;
const byte FunPin =/*пин*/2;
/*состояние 0 -вык 1 вкл*/
bool state;
unsigned long past;
const unsigned long time10s = 10000;
const unsigned long time15s = 15000;
void stand(bool s) {
  state = s;
  switch (state) {
    case 0:
      digitalWrite(FunPin, HIGH); //вентилятор выключен
      break;
    case 1:
      digitalWrite(FunPin, LOW); //вентилятор  включен
      break;
  }
}
//---------------------------
void setup() {
  pinMode(FunPin, OUTPUT);
  stand(0);
}

void loop() {
  unsigned long mill = millis();
  int foto = analogRead(FotoPin);
  switch (state) {
    case 0:
      if (foto > 800) past = mill;
      /*если свет включен то включить вентилятор */
      else if (mill - past >= time10s) stand(1);
      break;
    case 1:
      if (foto < 800) past = mill;
      /*если свет выключен долго то выключить вентилятор */
      if (mill - past >= time15s) stand(0);
      break;
  }
}
/*Скетч использует 934 байт (3%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 14 байт (0%) динамической памяти, оставляя 2034 байт для локальных переменных. Максимум: 2048 байт.
*/

И зря вы просите помощи, лучше сами. Так вы карму себе портите, пути к развитию отрезаете.

30andrew
Offline
Зарегистрирован: 17.11.2018

Да, да, конечно. Спасибо за мнение.

30andrew
Offline
Зарегистрирован: 17.11.2018

qwone пишет:

То у меня это компилируется. А если у вас не поддерживаются enum, то это же не моя вина.

http://cppstudio.com/post/8106/

Разобрался с компилятором, enum не причем. Все заработало. Спасибо за рабочие примеры.

30andrew
Offline
Зарегистрирован: 17.11.2018

Доброго времени суток всем! Наконец приехало из Китая UNO ии расставило все по местам! :) До этого насочинял разных версий программ управления вентилятором, втом числе и предпринял попытку модернизации чужих. Не работает... То есть работает, но не совсем так, как хотел бы. Столкнулся с пока необъяснимой для меня реакцией Ардуино - в ряде случаев плата игнорирует некоторые куски программы. Думал сначала, что до этих строчек просто дело не доходит, но потом все же постал, что это не так. Почему, однако, они игнорируются так и не понял. Привожу упрощенный пример пример программы от qwone, которую я  слегка переделал в процессе запуска на Ардуино, когда столкнулся с проблемами. Доработать я ее сначала хотел под свои требования, но остановился, поскольку столкнулся необъснимым отсутствием реакции устройства. Вот код:

/**/
const byte FotoPin =/*пин*/A0;
const byte FunPin =/*пин*/2;
/*состояние 0 -вык 1 вкл*/
byte state;
unsigned long past;
unsigned long maxtime;
const unsigned long time10s = 2000;
const unsigned long time15s = 3500;
const unsigned maxtime20s = 5000;
void stand(byte s) 
{
  state = s;
  switch (state) 
  {
    case 0:
      digitalWrite(FunPin, LOW); //вентилятор выключен
      break;
    case 1:
      digitalWrite(FunPin, HIGH); //вентилятор  включен
      break;
  }
}
//---------------------------
void setup() 
{
  pinMode(FunPin, OUTPUT);
  stand(0);
  maxtime = 0;
}
void loop() 
{
  unsigned long mill = millis();
  int foto = analogRead(FotoPin);
  switch (state) {  
   case 0:
       if (foto > 800) stand(1);
    break;
    case 1:
    if (foto > 800 && maxtime == 0) maxtime = mill;
    else  if (foto > 800 && mill - maxtime >= maxtime20s) {stand (0); maxtime=0;}
    if (foto < 800) {stand(0); maxtime=0;}
    break;          
  }
}

Код компилируется, но не работает 3-я снизу строка:

 else  if (foto > 800 && mill - maxtime >= maxtime20s) {stand (0); maxtime=0;}

Может быть кто-то подскажет, в чем причина?

30andrew
Offline
Зарегистрирован: 17.11.2018

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

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

800+... значит уровень на выходе весьма высокий... тогда может быть вместо аналога использовать цифру?

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

Между строками №№ 34 и 35 поставьте вывод переменной foto в монитор порта. Посмотрите чему она равна и тогда будете рассуждать ужес открытыми глазами.

И ещё (это не причина проблемы, но всё-таки) в выражении "mill - maxtime >= maxtime20s" у Вас собрано ТРИ разных типа данных в одном выражении. наверняка компилятор предупреждает Вас об этом (если предупреждения не выключены). Старайтесь такого избегать.Уж по крайней мере, не смешивайте знаковые и беззнаковые значения.

sadman41
Offline
Зарегистрирован: 19.10.2016

Как оно может компилироваться при const unsigned maxtime20s = 5000; ?

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

sadman41, а что не так с этой строкой? Я что-то ... можустал к вечеру.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

sadman41 пишет:

Как оно может компилироваться при const unsigned maxtime20s = 5000; ?

const unsigned long maxtime20s=5000;

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Но для простоты понимания лучше воспользоваться автоматом с четырьмя состояниями

sadman41
Offline
Зарегистрирован: 19.10.2016

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

sadman41, а что не так с этой строкой? Я что-то ... можустал к вечеру.

Непонятно к какому типу unsigned пристегивается. Или сообщение с кодом подправили враги...

30andrew
Offline
Зарегистрирован: 17.11.2018

sadman41 пишет:

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

sadman41, а что не так с этой строкой? Я что-то ... можустал к вечеру.

Непонятно к какому типу unsigned пристегивается. Или сообщение с кодом подправили враги...

Точно! Враги! :) (Шутка, конечно). - Это результат параллельной работы на нескольких вкладках компилятора. Спасибо за замечание.

30andrew
Offline
Зарегистрирован: 17.11.2018

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

Между строками №№ 34 и 35 поставьте вывод переменной foto в монитор порта. Посмотрите чему она равна и тогда будете рассуждать ужес открытыми глазами.

Спасибо, попробую.

30andrew
Offline
Зарегистрирован: 17.11.2018

ELITE пишет:

800+... значит уровень на выходе весьма высокий... тогда может быть вместо аналога использовать цифру?

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

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

sadman41 пишет:

Непонятно к какому типу unsigned пристегивается. Или сообщение с кодом подправили враги...

Да, Господь с Вами,это Вы чего-то подзабыли, освежите. Голый unsigned вполне допустим и означает беззнаковый int, чего уж тут непонятного.

sadman41
Offline
Зарегистрирован: 19.10.2016

Тут Вы правы - даже и не помню, когда осмысленно использовал unsigned без типа. Да и с типом тоже - все intX_t/uintX_t пользую.

30andrew
Offline
Зарегистрирован: 17.11.2018

qwone пишет:

Но для простоты понимания лучше воспользоваться автоматом с четырьмя состояниями

Хотел сделать так, но не получилось... А получилось, но подругому.

 

30andrew
Offline
Зарегистрирован: 17.11.2018

qwone пишет:

Но для простоты понимания лучше воспользоваться автоматом с четырьмя состояниями

Добрый вечер! Путем неимоверных усилий наконец-то удалось достичь того, чего хотелось! :)))

(вечера, к сожалению, зимой короткие, да и на работе поздно задерживаться приходится. Но это лирика.

Напомню, что хотел сделать: 1)включаем свет, 2)с задержкой включается вентилятор, 3)горит свет некое время - вентилятор работает, 4)выключаем свет, 5)вентилятор выключается с заданной задержкой, 6)если забыли выключить свет - вентилятор выключается через некое заданное максимальное время, например 20-30мин. Выключение вентилятора можно совместить с принудительным выключением света.

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

/**/
const byte FotoPin =/*пин*/A0;
const byte FunPin =/*пин*/2;
enum state_t {FunOFF = 0, FunON} state; //статус управления вкл/выкл
unsigned long past; //время таймера включения
unsigned long past1; //время таймера выключения
byte flag; //логический флаг состояния включения света
const unsigned long time10s = 1000; //уставка задержки включения
const unsigned long time15s = 1500; //уставка задержки выключения
const unsigned long time20s = 6000; //уставка максимально допустимого времени работы
void stand(state_t s) {
  state = s;
  switch (state) {
    case FunON:
      digitalWrite(FunPin, HIGH); //вентилятор включен
      break;
    case FunOFF:
      digitalWrite(FunPin, LOW); //вентилятор  выключен
      break;
  }
}

//_______________________________
void setup() {
  pinMode(FunPin, OUTPUT);
  stand(FunOFF); //начальное условие - вентилятор выключен
  past=0;
}
void loop() {
  unsigned long mill = millis(); //запускаем таймер
  int foto = analogRead(FotoPin);
  {
  if (foto > 800 && past == 0)  past = mill;    //начало работы таймера включения с "нуля", если включили свет.
  if (foto <= 800 && past1 == 0)  past1 = mill; //вводим второй таймер и определяем условие его запуска, если выключен свет
  if (foto > 800 && mill - past == time10s) {stand(FunON); past1=0;}    //условия задержки включения вент. после включения света
  if (foto<= 800 && mill - past1 == time15s) {stand(FunOFF); past = 0;}     //условия задержки выключения вент. после выключения света
  if (foto > 800 && mill - past >= time20s) {stand(FunOFF); flag = 1;}    //условие отключения вентилятора при включенном свете и флаг состояния включения света
  if (foto<= 800 && flag == 1) {past=0; flag = 0;}    //подготовка к новому циклу работы после отключения света - начальные установки параметров flag и past
   }
}

Код работает исправно (по крайней мере на макетке). Нужно промышленное тестирование :))) И спасибо Всем за участие и посильную помощь.

А что касается автомата с четырьмя состояниями - хотел, потратил много времени, но не получилось...-  не хватило опыта. Пришлось изменить тактику.