код - можно ли проще?

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

Уберите строки 12,13 и 17 и посмотрите что получается ..

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

А получается что пройдя 1 датчик, включаем все, пауза пошла!

Прошли второй, пауза продлилась(что нам и надо), НО мы так же передали лампы от 2 датчика, и выключение идет как будто сработали 1+2(а вот этого не надо, нам это надо только когда  идет включение, одновременное срабатывание датчикОВ)

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

Ещё раз, ничего не понятно.

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

Эта ситуация - ровно та, что Вы и хотели когда "сработали оба датчика" .. нет? А как по вашему различаются эти две ситуации?

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

 

Эта ситуация - ровно та, что Вы и хотели когда "сработали оба датчика" .. нет? А как по вашему различаются эти две ситуации?

Это ситуация ТА, когда оба датчика сработали ДО включения паузы! Если же 2 датчик сработал ВО время паузы, этого не надо(надо пауза ++)!

ПАУЗА и ВКЛЮЧЕНИЕ ламп, две разные вещи, не так?

Вот почему рисуя схему, я рисовал отдельную ветку ПАУЗА, что бы мы крутились только в ней, когда все горит, соответственно идет пауза и сработал любой из датчиков(или оба сразу)!

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

Во-от.. то есть ДВЕ разных ситуации в вашем ТЗ: "одновременное" срабатывание двух датчиков и, в этом случае, лампы надо включать с обоих сторон, и "повторное срабатывание" одного из датчиков в процессе ожидания паузы, в этом случае ничего менять не требуется, а надо только лишь продлить паузу.

А поскольку совсем "одновременно" быть не может, хотя бы потому что хоть и очень быстро, но датчики проверяются последовательно в цикле, то одновременность срабатывания трактуем как "срабатывание второго датчика в течении процесса включения первого сработавшего" .. то есть пока не загорелись все лампы от первого датчика (процесс датчика в режиме включения, его шаг>0) и не установлен его режим выключения И соответственно не запущена пауза .. значит "одновременно". А вот если он уже в режиме выключения, значит "идет пауза" или она уже и вовсе прошла и лампы уже начали выключаться.

Как отсюда видно, это состояние куда как проще проверять проверкой шага другого датчика (>0 - включение, <0 - выключение, ==0 - неактивен вовсе), а вовсе не "кончилась ли пауза" .. (она могла и не начаться ещё).

Вот теперь предлагаю точнее переформулировать ТЗ. Что должна делать схема в тех или иных комбинациях состояний процессов и начать проектирование заново. :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Издеваетесь? :)

"Во-от.. то есть ДВЕ разных ситуации в вашем ТЗ: "одновременное" срабатывание двух датчиков и, в этом случае, лампы надо включать с обоих сторон, и "повторное срабатывание" одного из датчиков в процессе ожидания паузы, в этом случае ничего менять не требуется, а надо только лишь продлить паузу."

Именно так!

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

Ни сколько. Перечитайте, нигде ни единожды условие одновременности включения четко озвучено не было. А это ключевой момент. Так часто бывает в "хотелках" заказчиков: "ну это же очевидно!" .. да ни разу. До сих пор "одновременное включение с двух сторон" в скетчах трактовалось как "включение второго датчика не позднее выключения первого" .. то есть "пока идет пауза". А теперь, оказывается, что одновременное включение это только тогда, когда второй датчик срабатывает ДО завершения включения ламп первым .. то есть ДО начала паузы. .. или нет? :)

Вот и предлагаю вам прописать все комбинации состояний (их по 4 на каждый датчик): "датчик неактивен" (шаг==0), "датчик включает лампы" (шаг>), "датчик ждет паузу ДО начала выключения" и "датчик уже начал выключать лампы" .. для двух датчиков - табличка 4х4 .. итого 16 комбинаций. И в каждом сочетании состояний датчиков может сработать "датчик движения" .. любой. На самом деле не все комбинации ведут к принципиально разному поведению, но прописать их надо (для себя) все.

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

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Так что делать то теперь?

 

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

1. датчик  №1 сработал - Включение ламп 1,2,3,4,5,6; пауза; Выключение 1,2,3,4,5,6

2. датчик №2 сработал - Включение ламп 6,5,4,3,2,1; пауза; Выключение 6,5,4,3,2,1

3. датчики №1 и №2 сработали оновременно(или пока идет включение от одного из них) - Включение ламп с двух     сторон  (от краев к центру)  1,2,3,4,5,6 - 6,5,4,3,2,1 

    Выключение ламп от точки их встречи (при включении) и (от центра к краям) 6,5,4,3,2,1 - 1,2,3,4,5,6

4. ЕСЛИ датчик №1 производит включение ламп и в этот момент  срабатывает датчик №2 преход в п.3(аналогично     для датчика №2)

5.  ЕСЛИ любой из п.1, п2, п3 произвел включение ламп, началась пауза и в  момент паузы  срабатывает любой из датчиков то;

     ничего не включаем, не запоминаем, а только продливаем паузу! Выключение производим согласно тому пункту, от которого произошло включение!

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

Нет, нет нет. Перечитайте мой последний пост и пост в начале темы #28 кажется .. Как и тогда, я Вам предлагаю пойти не от наблюдаемых хотелок "сработал датчик -> что-то делаем", а составить таблицу состояний вашей программы и уже потом посмотреть что должно происходить если датчик "сработал" в том или ином состоянии программы (автомата): "включали лампы -> сработал ещё раз" - что делать? "выключали лампы->сработал второй датчик" - а тут что? и т.д. НАОБОРОТ.

Такая табличка и описание действий по наступлению событий вообще-то зовется "таблицы переходов конечных автоматов".. чем и является ваша программа - 2 простых конечных автомата.

 

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

слов нет.... и логика закончилась!

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

не очень понимаю ваш энтузиазм по этому поводу, вроде как я Вам сразу предлагал начать с уточнения ТЗ .. ну да ладно, "проехали". :)

Ваши п.4,п.5 поста 309 как раз близко к тому, что я предлагаю вам сделать аккуратно и полностью. Пример для "независимого" анализа ситуаций (каждый датчик и его автомат управления как-бы сам по себе):

Датчик1 (Д1) : (0)неактивен  , (1)включает лампы, (-1 и П<И)ждет паузу, (-1 и П>И)выключ.
"сработал Д1": настройка "1" , пофиг, уже вкл.  , новая Пауза(старт)  , настройка сост."1"
"сработал Д2": пофиг, не наш , пофиг, не наш    , новая Пауза         ,  ???

Заметим, что действие "пофиг" означает что в этой ситуации можно применить ЛЮБОЕ действие, какое удобно, а равно не применять никакого. Отсюда:

1. Срабатывание "своего датчика" (Д1) может производить настройку режима включения практически для всех его состояний, кроме "ждет паузу". И оно определяется ДВУМЯ условиями, а не одним: датчик должен быть подготовлен к вЫключению И ещё не закончилась пауза.

2. Срабатывание "чужого датчика" (Д2 для состояний автомата Д1) .. должно тоже продлить паузу в случае ожидания и "что-то предпринять" (а надо ли и что? - надо определить действие, где вопросики) в случае, если "чужой" автомат УЖЕ начал выключение ламп. То есть, это снова "неописанная в ТЗ" ситуация: лампы включены от Д1, прошла пауза и автомат Д1 УЖЕ начал выключать лампы со своего конца .. и тут сработал датчик Д2 .. что делать?

.. и это для как-бы независимого управления .. а у вас есть зависимость: "одновременное включение" .. то есть вот такую табличку надо расписать для всех сочетаний 4х4 и для обоих датчиков определить "что делать".

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

не очень понимаю ваш энтузиазм по этому поводу, вроде как я Вам сразу предлагал начать с уточнения ТЗ .. ну да ладно, "проехали". :)

 

Это уже не энтузиазм, это уже истерика! :)

Как должно быть, я знаю, а как это выразить "правильно" для Вашего понимания, нет!

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

?!? Для "моего"-то зачем? Программа ваша, для себя и выражайте. Я вам только помогаю освоить "автоматное программирование" несколько "вычурным" способом, поскольку сразу (в начале темы) Вы предпочли кодить, вместо того, чтобы доделать ТЗ то текущего вопросу.. как видите мы пришли "к тому же самому" с чего начинали.

Как только разберетесь со всеми взаимопересечениями состояний автоматов управления лампами и станет понятно что и какими условиями проверяется .. просто дополняете код поста #219 после строки 117 и до строки 121 требуемыми проверками условий и действий по ним и всё. Остальное переделывать не потребуется. 117-121 - это блок "датчик сработал" .. и вот в нем и нужно будет правильно прописать все действия для обоих датчиков: какой перевести во включение, какой перевести в "неактивен" или тупо продлять паузу .. и всё. :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016
if( cur->lamp == cur->max )

Вот тут что? Я так понимаю; (Включили все лампы?)

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

Да.

 

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Ну по логике, можно же поставить проверку на лампы, если все горит, пауза++?

Почему не получается?

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

Как предлагаете это сделать?

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Незнаю! Просто мысли в слух!

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

Смотрите код #219. Что и чему будет равно, в ситуации когда все лампы горят? Там есть по меньшей мере 3 варианта.. :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Вот здесь


cur->lamp = (num==0? 0 : MAX_LED-1);

в зависимости от того какой датчик, первая лампа будет = или 0 или MAX_LED-1   ?


cur->max = (num==0? MAX_LED : -1);

в зависимости от того какой датчик, последняя лампа будет = или MAX_LED или -1 ?

 

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

Да, именно так.

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Мне просто надо ХОРОШО разобраться что вообще написано в коде, и что за что отвечает! Для меня пока это только набор каких то цифорок и символов! :) Ну по чуть понимаю! Читаю! :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

Смотрите код #219. Что и чему будет равно, в ситуации когда все лампы горят? Там есть по меньшей мере 3 варианта.. :)

шаг = -1.

ну лампы как выше писал!

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

Да. Это один из вариантов. После того как включили все лампы шаг устанавливается в -1. Верно. Ещё вариант: пробежаться по списку ламп и убедиться что у всех яркость - максимальна (255). Третьего нет, ошибся. :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

То что в скобках {} выполняется не по очереди, а как бы сразу?

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

Последовательно "друг за дружкой".

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

как вывести в порт отсчет пузы?(чтоб типо как яркость посмотреть )

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

Также. Serial.print(startedPause, 10); тут просто указываете "основание" в какой системе счисления вам отрисовать чиселку.

можно прямо внутри вызвать millis(), типа так: Serial.print( millis(), 10); или посмотреть разницу Serial.print( millis()-startedPause, 10);

Только не забывайте, что millis() возвращает абсолютное количество миллисекунд, прошедшее с момента запуска скетча.

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Короче не важно! Еще этим голову забивать!

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

 Ещё вариант: пробежаться по списку ламп и убедиться что у всех яркость - максимальна (255). 

Типо так?

if (fades[fadeControl[num].lamp].bright < 255)

 

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

Нет. Так вы проверите яркость только одной лампы, номер которой хранится в fadesControl[num].lamp, а чтобы убедится что ВСЕ лампы включены на максиум, надо пробежаться по всем лампам в цикле и посчитать сколько включено и после цикла сравнить с общим количеством ламп. Типа так:

uint8_t onLamp = 0;
for( uint8_t num=0; num<MAX_FADES; num++){
  if( fades[num].bright == 255 )
    onLamp++;
}
if( onLamp == MAX_FADES) { /*вот тут точно все включены :) */}

Проще проверять шаг<0 И пауза ещё не кончилась .. потому как, ежели она "кончилась", то лампы начали выключаться..

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Как же шаг будет < 0 если в самом конце мы его cur->step = 0;

вообще я думал что то типо так:

if ((cur->step < 0) && millis() - startedPause <= WAIT_PAUSE)

 

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

Да, все верно думаете. Когда все лампы выключены, автомат сам себя переводит в состояние "неактивен" (шаг==0), а когда он все включил, то тоже переводит сам себя в состояние "буду выключать" (шаг==-1), и чтобу различить "уже выключаю" и "буду" и нужна дополнительная проверка паузы. Так что все верно: ваша проверка смотрит "готовность выключения" .. шаг - настроен И пауза ЕЩЁ не кончилась.

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Но почему то не работает! :(

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

Так смотря куда вставляете .. показывайте код, раз "не работает". :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016
if( digitalRead(cur->pir_pin) )
    {
     if ((cur->step < 0) && millis() - startedPause <= WAIT_PAUSE)
  {
    cur->step = 1;
    cur->lamp = (num==0? 0 : MAX_LED-1);
    cur->max  = (num==0? MAX_LED : -1);
  }
    startedPause = millis();
    }

Как всегда, по логике! :)

нам же надо обойти здесь

{
    cur->step = 1;
    cur->lamp = (num==0? 0 : MAX_LED-1);
    cur->max  = (num==0? MAX_LED : -1);
  }

 

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

Ну так это только обход 1 состояния из 4-х возможных (и "наоборот" даже)! А "остальные" как жеж? (см. #312) :)

Там "что указано"? Что начинаем включение если а) неактивен; б) уже включает (пофиг, пробежимся заново); г) уже выключает.

А у Вас? Условие для состояния "в" (готов к выключению, жду паузу. Пауза ещё НЕ завершена) и в скобках указано .. "начать включение". Т.е. с точностью до "наоборот". :)

Может как-то так?

if( digitalRead(cur->pir_pin) )
{
    if( !( (cur->step < 0) && (millis() - startedPause <= WAIT_PAUSE) ) )
    {
        cur->step = 1;
        cur->lamp = (num==0? 0 : MAX_LED-1);
        cur->max  = (num==0? MAX_LED : -1);
    }
    startedPause = millis();
}

// или преобразуюя условия по правилам логических выражений:

if( digitalRead(cur->pir_pin) )
{
    if( cur->step >= 0 || millis() - startedPause > WAIT_PAUSE )
    {
        // сюда попадаем если: а) неактивен (==0); б) включает (>0);
        // ИЛИ: <0 (ничего из предыдущего!) И прошла пауза .. т.е. г) выключает
        cur->step = 1;
        cur->lamp = (num==0? 0 : MAX_LED-1);
        cur->max  = (num==0? MAX_LED : -1);
    }
    startedPause = millis();
}

Но это будет реализация только реакции на верхнюю строчку таблицы состояний автомата .. независимо от второй части. Это решает даже проблему "драки за лампу", тем что пауза у нас единая. И второй датчик автоматически прекратит выключение, если его уже начал (его состояние "г") .. но это - "не фсё"! :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Ну незнаю что это дало нам, изменений нет :(

Разбираюсь... :)

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

Каких изменений Вы ждали и чего нет? Опишите как оно теперь работает..

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

впринципе изменений я пока не вижу, да, все как было так и работает! Паузу посмотреть так и не могу, не разобрался куда ставить! 

 if( cur->step >= 0 || millis() - startedPause > WAIT_PAUSE )
 если здесь хотя бы в одном ДА, заходим сюда 
   {
        cur->step = 1;
        cur->lamp = (num==0? 0 : MAX_LED-1);
        cur->max  = (num==0? MAX_LED : -1);
    }

если НЕТ, не заходим! Так?

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

Угу.

Не должно быть "как было так и работает".. во-первых, теперь переход в состояние включения НЕ производится при повторном срабатывании датчика во время паузы, а просто будет продляться пауза. А во-вторых, теперь нет драки за лампу, поскольку повторное срабатывание одного из датчиков в обязательном порядке (после скобок) продляет паузу. И, тем самым, если второй датчик собирался что-то выключать или даже уже начал что-то выключать - он "тормознется" и никакой драки за лампу не произойдет.

Вам надо решить "что делать" в ситуации, определенной вопросиками в посту #312 .. то есть, пусть первый датчики поначалу сработали "одновременно" (второй во время включения от первого) и часть ламп загорелась "навстречу" друг-другу .. и вот теперь, когда прошла пауза и оба автомата начали выключать лампы (это всегда будет делаться одновременно - пауза одна!), внезапно сработал первый датчик.

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

Если как сейчас, то произойдет следующее: первый автомат переведет себя в режим включения, продлит паузу и включит ВСЕ лампы заново, а второй автомат обнаружит что пошла новая пауза и .. перейдет в режим ожидания с тем номером лампы, который у него остался "текущий" (->lamp) .. по истечению новой паузы оба автомата начнут выключать лампы, но первый будет выключать со своего конца, а второй .. с той лампы на которой остановился.

На примере: имеем 6 ламп. До повторного срабатывания второй датчик успел отключить лампы 5,6 и его текущая лампа 4 .. датчик 1, продлив паузу остановит процесс на этой 4-й лампе и сам(!) включит лампы 5,6 .. по завершению паузы лампы будут выключаться в порядке:

1 - первым датчиком И 4 - вторым датчиком, затем

2 - первым датчиком И 3 - вторым датчиком, затем

.. 5,6 - снова первым датчиком .. так надо? Если нет, то "как надо"? :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

Вам надо решить "что делать" в ситуации, определенной вопросиками в посту #312 .. то есть, пусть первый датчики поначалу сработали "одновременно" (второй во время включения от первого) и часть ламп загорелась "навстречу" друг-другу .. и вот теперь, когда прошла пауза и оба автомата начали выключать лампы (это всегда будет делаться одновременно - пауза одна!), внезапно сработал первый датчик.

Посмотрел, прикольно однако :) Но,

надо приаритет на 1 датчик! Так как 1+2 датчики, редкое явление!

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

Зачем? Вы же можете эту ситуацию обработать точно таким же условием .. надо просто решить "что делать" если она произошла. К примеру, можно в таком разе второй датчик "сбрасывать" на начало выключения заново и когда пройдет пауза он начнет не с 4-й, а заново с 6-й лампы .. или тупо переводить его в состояние "неактивен" и, в этом случае, выключением будет заниматься тот автомат, который "сработал повторно" в процессе начатого выключения. Или придумать ещё какое действо ..

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

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

Я это и имел ввиду!

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

Ну, тогда Вам осталось сформулировать условие пункта "г" для "чужого автомата". "Свой автомат" - управляется через указатель cur, а вам нужен "второй"..

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

Не должно быть "как было так и работает".. во-первых, теперь переход в состояние включения НЕ производится при повторном срабатывании датчика во время паузы, а просто будет продляться пауза.

Почему тогда во время паузы от 1 датчика, при срабатывании 2, пауза вроде как ставится с начала, НО и все равно выключение от двух датчиков!(как будто 1+2)

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

Как это "почему"? Попробуйте ответить самостоятельно. :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Так я ЭТО и хочу убрать!

Когда идет пауза, ЛЮБОЙ из датчиков(1,2,1+2), надо игнорировать на включение, А только продливать паузу!

SOCHINEC
Offline
Зарегистрирован: 01.05.2016

Arhat109-2 пишет:

теперь переход в состояние включения НЕ производится при повторном срабатывании датчика во время паузы

Вот это разве не ЭТО?

Или это относится только к тому датчику, который включил эту паузу?