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

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

Пост #192 содержит код loop(), в котором все ветки ДРАКОН-схемы расписаны по отдельности, а не собраны вместе. В предыдущем скетче, у вас ветки объединены за счет сложных условий внутри if(). В частности один и тот же код занимается как включением так и ВЫключением ламп. Так ведь? А поскольку тот "объединенный" вариант вызывает трудности в розыске какой кусок как взаимодействует с остальными .. то я вам и развернул все эти условия в посту #192.

Вот и хочется увидеть результат вашего труда: полный скетч с кодом из #192 И перетасованный так, чтобы все ветки относящиеся к датчику1 были раньше чем все ветки датчика2. То есть сначала вернемся несколько назад увеличив скетч, а потом двинемся далее.

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

Смотрю в книгу вижу ф....у!))) Это если честно!)))

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

В #192 они и так вроде стоят в своем порядке, сначала 1 датчик, затем второй! Или я чего то не понимаю!?

Общее у них только

if( isDayNow() ) return;
millis() - startedAt >= WAIT_1
curTime = millis();

я наверно просто не пойму, но вот


/ ветка1. "Царская дорога" (самое просто и 3/5 суточного исполнения): Если светло - выходим.
// *прим.: тут надо ещё добавить код, выключающий лампы, если они были ещё включены.
  if( isDayNow() ){ /*выключить всё*/ return; }

// ветка2.1 "Темно" - ждем датчик1:
  if( digitalRead(pirPin1) ){
    isGo1 =  1;              // датчик1 сработал: переключаем на ветку 3.1 и подготавливаем данные
    lamp1=0;                 // включение от меньшей к большей, яркость по +1 (isGo1)
    max1 = MAX_LED;
  }
   
// ветка 3.1 поштучно включаем лампы от меньшей к большей:
  if( isGo1 == 1 ){

    // подветка 3.1.1 "текущая лампа уже включена? перейти к следующей"
    if( fades[lamp1].bright == 255 ){
      lamp1++;
    }


else{
      // ветка "нет" 3.1.1: "добавлять яркость по isGo1, каждые WAIT_1 мсек"
      fadeLED(lamp1, isGo1);
    }
  }
// Ветка 4.1 "Лампы для датчика1 - включили все"? Включаем паузу и переходим к ветке 5.1
  if(  isGo1 == 1 && lamp1 == max1 ) // мы включали лампы И прошли все?
  {
    // подветка "ДА" 4.1: "включаем паузу заново, переходим к ветке выключение1"
    startedPause = millis(); // фиксируем начало отсчета паузы
    isGo1 = -1;              // .. после паузы будем выключать (5.1) - меняем направление яркости и шаг
    lamp1= 0;                // .. снова в порядке от меньшей к большей
    max1 = MAX_LED;
  }
// Обе подветки ожидания выключения работают от одной паузы, фиксируем время тут:
  curTime = millis();

// Ветка 5 "прошла пауза?"
  if( curTime - startedPause >= WAIT_PAUSE )
  {
    // подветка 5.1 "Выключение ламп датчика1"
    if(
        (isGo1 == -1)
    ){
      // Подветка 5.1.1 "Текущая лампа УЖЕ выключена?"
      if( fades[lamp1].bright == 0 ){
        lamp1++;  // "ДА" переходим к следующей (к большей!):
      }else{
        fadeLED(lamp1, isGo1);  // уменьшаем яркость на isGo1 каждые WAIT_1 мсек: 
      }
    }

    // Подветка 5.3 "Все лампы датчика1 выключены?"
    if( isGo1 == -1 && lamp1 == max1 ){
      isGo1 = 0; // .. ну и ладушки, всё погасло
    }
Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Видимо это я не так объясняю чего от Вас хочу .. смотрите, к первому датчику относятся пункты 3, 5, .. а ко второму 4, 6.. то есть идут "вперемежку", несмотря на то что это как-бы "независимые" ветки и исполнять их можно в ЛЮБОЙ последовательности (каждая ветка исполняется только при своем условии, которое изменяется глобально, то есть практически независимо от порядка в скетче) .. вот мне и хочется, чтобы Вы самостоятельно переставили пункты со своими условиями так, чтобы все ветки ДРАКОН-схемы, относящиеся к первому датчику шли друг за другом, "подряд". А за ними так же подряд уже шли все ветки, относящиеся ко второму датчику.

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

Опять не вкурил! Но, подряд это так я думаю

  if( isDayNow() ){ /*выключить всё*/ return; }

// ветка2.1 "Темно" - ждем датчик1:
  if( digitalRead(pirPin1) ){
    isGo1 =  1;              // датчик1 сработал: переключаем на ветку 3.1 и подготавливаем данные
    lamp1=0;                 // включение от меньшей к большей, яркость по +1 (isGo1)
    max1 = MAX_LED;
  }



// Разделяем эти условия на отдельные ветки, дабы не путаться:

// ветка 3.1 поштучно включаем лампы от меньшей к большей:
  if( isGo1 == 1 ){

    // подветка 3.1.1 "текущая лампа уже включена? перейти к следующей"
    if( fades[lamp1].bright == 255 ){
      lamp1++;
    }else{
      // ветка "нет" 3.1.1: "добавлять яркость по isGo1, каждые WAIT_1 мсек"
      fadeLED(lamp1, isGo1);
    }
  }


// Ветка 4.1 "Лампы для датчика1 - включили все"? Включаем паузу и переходим к ветке 5.1
  if(  isGo1 == 1 && lamp1 == max1 ) // мы включали лампы И прошли все?
  {
    // подветка "ДА" 4.1: "включаем паузу заново, переходим к ветке выключение1"
    startedPause = millis(); // фиксируем начало отсчета паузы
    isGo1 = -1;              // .. после паузы будем выключать (5.1) - меняем направление яркости и шаг
    lamp1= 0;                // .. снова в порядке от меньшей к большей
    max1 = MAX_LED;
  }



// Обе подветки ожидания выключения работают от одной паузы, фиксируем время тут:
  curTime = millis();

// Ветка 5 "прошла пауза?"
  if( curTime - startedPause >= WAIT_PAUSE )
  
    // подветка 5.1 "Выключение ламп датчика1"
    if(
        (isGo1 == -1)
    ){
      // Подветка 5.1.1 "Текущая лампа УЖЕ выключена?"
      if( fades[lamp1].bright == 0 ){
        lamp1++;  // "ДА" переходим к следующей (к большей!):
      }else{
        fadeLED(lamp1, isGo1);  // уменьшаем яркость на isGo1 каждые WAIT_1 мсек: 
      }
    }

    // Подветка 5.3 "Все лампы датчика1 выключены?"
    if( isGo1 == -1 && lamp1 == max1 ){
      isGo1 = 0; // .. ну и ладушки, всё погасло
    }

Если убрать все подветки, как раз и будет по порядку!


  if( isDayNow() ){ /*выключить всё*/ return; } // основное условие, для всех датчиков

// ветка2.1 "Темно" - ждем датчик1:
  if( digitalRead(pirPin1) )

// ветка 3.1 поштучно включаем лампы от меньшей к большей:
  if( isGo1 == 1 )

//Ветка 4.1 "Лампы для датчика1 - включили все"? Включаем паузу и переходим к ветке 5.1
  if(  isGo1 == 1 && lamp1 == max1 ) // мы включали лампы И прошли все?

// Обе подветки ожидания выключения работают от одной паузы, фиксируем время тут: 
curTime = millis();

 // Ветка 5 "прошла пауза?" 
  if( curTime - startedPause >= WAIT_PAUSE )

 // ветка 5.1 "Выключение ламп датчика1"
   if (isGo1 == -1) {isGo1 = 0;} // .. ну и ладушки, всё погасло

Кроме паузы, как то она все не на своем месте, мне кажется!:)

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

Угу. Условие с паузой "не на месте" .. продолжаем. Заметьте что под ним находится несколько веток от обоих датчиков, а вам надо их разделить по датчикам, но .. условие с паузой - одно. Стало быть "выбор невелик": откопировать условие паузы в обе разделяемые части. Должно получиться примерно так:

// Схема "Силуэт", обход веток датчиков последовательно:

// ветка1. "Царская дорога" она одна и разделять нечего

//---группа1--- датчик1:
// ветка2.1 "Темно" - ждем датчик1:
// ветка 3.1 поштучно включаем лампы от меньшей к большей:
// Ветка 4.1 "Лампы для датчика1 - включили все"? Включаем паузу и переходим к ветке 5.1
// Разделяем подветки ожидания:
  curTime = millis();
  // Ветка 5 "прошла пауза?"
    // подветка 5.1 "Выключение ламп датчика1"
    // Подветка 5.3 "Все лампы датчика1 выключены?"
  } // конец ветки сработавшей паузы

//---группа2--- датчик2:
// ветка2.2 "Темно" - ждем датчик2:
// ветка 3.2. поштучно включаем лампы от большей к меньшей:
// Ветка 4.2 "Лампы для датчика2 - включили все"? Включаем паузу и переходим к ветке 5.2
// Разделяем подветки ожидания:
  curTime = millis();
  // Ветка 5 "прошла пауза?"
    // Ветка 5.2 "Выключение ламп датчика2"
    // Подветка 5.4 "Все лампы датчика2 выключены?"
  } // конец ветки сработавшей паузы

Вот, такое перестроение кода я от вас и жду. С вас перестроенный код.

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

А пока продолжим со схемой: Как видите, обе группы веток практически индентичны, и их можно "завернуть" в цикл и тупо повторять его исполнение дважды. Остается только одна "проблема": надо как-то правильно определяться с используемыми данными для каждого повтора цикла: какой lamp будет использован в коде для первого или второго датчика? :)

В общем, пока ждем ваш перестроенный код согласно этому порядку веток схемы.

SOCHINEC
Offline
Зарегистрирован: 01.05.2016
// Схема "Силуэт", обход веток датчиков последовательно:

 // ветка1. "Царская дорога" она одна и разделять нечего
  
  // if( isDayNow() ){ /*выключить всё*/ return; }
 //---группа1--- датчик1:
 // ветка2.1 "Темно" - ждем датчик1:
    if( digitalRead(pirPin1) ){isGo1 =  1; lamp1=0; max1 = MAX_LED;}
 // ветка 3.1 поштучно включаем лампы от меньшей к большей:
    if( isGo1 == 1 )

  { // подветка 3.1.1 "текущая лампа уже включена? перейти к следующей"
    if( fades[lamp1].bright == 255 ){lamp1++;}
    else{fadeLED(lamp1, isGo1);}
      }
 // Ветка 4.1 "Лампы для датчика1 - включили все"? Включаем паузу и переходим к ветке 5.1
    if(  isGo1 == 1 && lamp1 == max1 )
  {
    startedPause = millis();
    isGo1 = -1;              
    lamp1= 0;                
    max1 = MAX_LED;
    }
 // Разделяем подветки ожидания:
    curTime = millis();
    
 // Ветка 5 "прошла пауза?"
    if( curTime - startedPause >= WAIT_PAUSE )
 // подветка 5.1 "Выключение ламп датчика1"
  {
    if((isGo1 == -1))
   {
     if( fades[lamp1].bright == 0 ){lamp1++;}
     else
        {fadeLED(lamp1, isGo1);}
         }
    
 // Подветка 5.3 "Все лампы датчика1 выключены?"
    if( isGo1 == -1 && lamp1 == max1 ){isGo1 = 0;}
  }// конец ветки сработавшей паузы

 //---группа2--- датчик2:
 // ветка2.2 "Темно" - ждем датчик2:
    if( digitalRead(pirPin2) ){isGo2 =  1; lamp2 = MAX_LED-1; max2 = -1;}
 // ветка 3.2. поштучно включаем лампы от большей к меньшей:
    if( isGo2 == 1 )
    
   { // подветка 3.2.2 "текущая лампа уже включена? перейти к следующей"
    if( fades[lamp2].bright == 255 ){lamp1--;}
    else{fadeLED(lamp2, isGo2);}
      }
 
 // Ветка 4.2 "Лампы для датчика2 - включили все"? Включаем паузу и переходим к ветке 5.2
    if(  isGo2 == 1 && lamp2 == max2 )
  {
    startedPause = millis();
    isGo2 = -1;              
    lamp2= MAX_LED-1;                
    max2 = -1;
    }
 // Разделяем подветки ожидания:
    curTime = millis();
  
 // Ветка 5 "прошла пауза?"
    if( curTime - startedPause >= WAIT_PAUSE )
 // Ветка 5.2 "Выключение ламп датчика2"
   {
    if((isGo2 == -1))
   {
     if( fades[lamp2].bright == 0 ){lamp2--;}
        else
            {fadeLED(lamp2, isGo2);}
              }
 // Подветка 5.4 "Все лампы датчика2 выключены?"
    if( isGo2 == -1 && lamp2 == max2 ){isGo2 = 0;}
   }// конец ветки сработавшей паузы

Вроде бы так!

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

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

pirPin, isGo, lamp, max, .. и startedAt, которая внутри функции fadeLED(). Именно из-за того, что мы в обоих группах использовали одну и туже функцию, которая внутри себя сама считает задержку, получалось что время пауз на изменения яркости второй группы ламп практически никогда и не срабатывали - задержка всегда отрабатывалась в первой группе. Надо иметь 2 стартовых времени.

Давайте введем структуру данных, которая будет определять все параметры рабочего цикла включения/выключения, типа так:

typedef struct{
  uint8_t        pir_pin;   // номер пина для датчика движения
  char           step;      // бывшая переменная isGo, теперь это "шаг" изменения яркости.
  uint8_t        lamp;      // номер текущей лампы, которой изменяем яркость
  char           max;       // номер последней лампы (недосчитывая) ДО которой будем перебирать лампы
  unsigned long  startedAt; // начало текущей паузы шага изменения лампы
} FadeCycle;

И, соответственно, теперь можем объявить массив из двух схем управления по 1 для каждого датчика:

FadeCycle    fadeControl[2];

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

// Схема "Силуэт", обход веток датчиков последовательно:

// ветка1. "Царская дорога"
// if( isDayNow() ){ /*выключить всё*/ return; }

for(uint8_t num=0; num<2; num++)
{
  // ветка2 "Темно" - ждем датчик:
  if( digitalRead(fadeControl[num].pir_pin) )
  {
    fadeControl[num].step = 1;
    // группа 0: от меньшей к большей, группа 1: от большей к меньшей
    fadeControl[num].lamp = (num==0? 0 : MAX_LED-1);
    fadeControl[num].max  = (num==0? MAX_LED : -1);
  }
  // ветка 3 поштучно включаем лампы от меньшей к большей:
  if( fadeControl[num].step == 1 )
  {
    // подветка 3.1 "текущая лампа уже включена? перейти к следующей"
    if( fades[fadeControl[num].lamp].bright == 255 ){
      fadeControl[num].lamp += (num==0? 1 : -1);
    }else{
      fadeLED(num); // теперь сюда передаем номер группы!
    }
  }
  // Ветка 4 "Лампы для датчика - включили все"? Включаем паузу и переходим к ветке 5.1
  if( fadeControl[num].step == 1 && fadeControl[num].lamp == fadeControl[num].max )
  {
    startedPause = millis();
    fadeControl[num].isGo = -1;
    // и тут тоже устанавливаем начало и конец в зависимости от того какая группа управления:
    fadeControl[num].lamp = (num==0? 0 : MAX_LED-1);
    fadeControl[num].max = (num==0? MAX_LED : -1);
  }

  // Ветка 5 "прошла пауза?"
  curTime = millis();
  if( curTime - startedPause >= WAIT_PAUSE )
  {
    // подветка 5.1 "Выключение ламп датчика"
    if((fadeControl[num].step == -1))
    {
      if( fades[fadeControl[num].lamp].bright == 0 )
      {
        // Лампа выключена, переходим к следующей
        fadeControl[num].lamp += (num==0? 1 : -1);
      }else{
        // продолжаем выключать лампу этой группы
        fadeLED(num);
      }
    }
    // Подветка 5.2 "Все лампы датчика выключены?"
    if( fadeControl[num].step == -1 && fadeControl[num].lamp == fadeControl[num].max )
    {
      fadeControl[num].step = 0;
    }
  } // конец ветки сработавшей паузы
}

Ну и соответственно, саму функцию fadeLED() надо обучить использовать место для хранения задержек изменения яркости, и тем самым устранить предыдущий недостаток работы второй группы:

/**
 * Функция изменения яркости на 1 шаг state РАЗ в 10 миллисекунд
 * @param state: +1 -- включение; -1 -- выключение
 */
void fadeLED(uint8_t num)
{
  Led * ptr = &(fades[fadeControl[num].lamp]);          // врем. лок. указатель на структуру "лампа"

  if(
     millis() - fadeControl[num].startedAt >= WAIT_1    // пора изменять яркость?
     && (
        (fadeControl[num].step==1 && ptr->bright < 255) // включаем И есть куда?
        ||
        (fadeControl[num].step==-1 && ptr->bright > 0)  // или вЫключаем И есть куда?
      )
  ){
      fadeControl[num].startedAt = millis();            // новое время для отсчета следующей паузы

      ptr->bright += fadeControl[num].step;             // изменяем яркость
      analogWrite( ptr->pin, ptr->bright);              // устанавливаем на выходе

      Serial.print(" b="); Serial.println(ptr->bright); // передаем данные в порт для отладки
  }
}

Собрать всё воедино и проверить на очепятки и пропуски, сверив со схемой.

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

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

// Схема "Силуэт", обход веток датчиков последовательно:

// ветка1. "Царская дорога"
// if( isDayNow() ){ /*выключить всё*/ return; }

for(uint8_t num=0; num<2; num++)
{
  if( digitalRead(fadeControl[num].pir_pin) )
  {
    fadeControl[num].step = 1;
    fadeControl[num].lamp = (num==0? 0 : MAX_LED-1);
    fadeControl[num].max  = (num==0? MAX_LED : -1);
  }
  if(
      (fadeControl[num].step > 0)                      // если включаем лампы, то сразу
      || (
           (fadeControl[num].step < 0)                 // а вот если вЫключаем, то
           && (millis() - startedPause >= WAIT_PAUSE)  // по истечению паузы
        )
  ){
    if( fadeControl[num].step > 0 && fades[fadeControl[num].lamp].bright == 255 )
    {
      fadeControl[num].lamp += (num==0? 1 : -1);
      if( fadeControl[num].lamp == fadeControl[num].max )
      {
        startedPause = millis();
        fadeControl[num].step = -1;
        fadeControl[num].lamp = (num==0? 0 : MAX_LED-1);
        fadeControl[num].max = (num==0? MAX_LED : -1);
      }
    }else
      if( fadeControl[num].step < 0 && fades[fadeControl[num].lamp].bright == 0 )
      {
        fadeControl[num].lamp += (num==0? 1 : -1);
        if( fadeControl[num].lamp == fadeControl[num].max )
        {
          fadeControl[num].step = 0;
        }
      }else{
        fadeLED(num); // теперь сюда передаем номер группы!
      }
  }
}

Примерно, как-то так все сворачивается обратно. :)

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

Ну и напоследок, работа с указателями. Если мы сразу, в начале цикла заведем указатель на структуру fadeControl[num], то он не изменяется внутри цикла, а стало быть можно сделать типа так:



// if( isDayNow() ){ /*выключить всё*/ return; }

for(uint8_t num=0; num<2; num++)
{
  FadeCycle * cur = &(fadeControl[num]);

  if( digitalRead(cur->pir_pin) )
  {
    cur->step = 1;
    cur->lamp = (num==0? 0 : MAX_LED-1);
    cur->max  = (num==0? MAX_LED : -1);
  }
  if(
      (cur->step > 0)                                  // если включаем лампы, то сразу
      || (
           (cur->step < 0)                             // а вот если вЫключаем, то
           && (millis() - startedPause >= WAIT_PAUSE)  // по истечению паузы
        )
  ){
    if( cur->step > 0 && cur->lamp].bright == 255 )
    {
      cur->lamp += (num==0? 1 : -1);
      if( cur->lamp == cur->max )
      {
        startedPause = millis();
        cur->step = -1;
        cur->lamp = (num==0? 0 : MAX_LED-1);
        cur->max = (num==0? MAX_LED : -1);
      }
    }else
      if( cur->step < 0 && fades[cur->lamp].bright == 0 )
      {
        cur->lamp += (num==0? 1 : -1);
        if( cur->lamp == cur->max )
        {
          cur->step = 0;
        }
      }else{
        fadeLED(num); // теперь сюда передаем номер группы!
      }
  }
}

Ну и вызво функции fadeLed остался один, и её можно развернуть сюда напрямую. Оставим, ибо некритично, зато понятней.

P.S. Любители С++ теперь могут проявить свою фантазию и создать базовый класс FadeCycleAbstract, который будет перечислять свойства объекта "схема включения ламп", они тут уже перечислены в виде структуры, далее отнаследовать 2 класса с разными схемами управления "от меньшей к большей" и "от большей к меньшей" и создать массив из 2 объектов ровно по 1 на каждый дочерний класс. И только "потом" показать как "синтаксический сахар" улучшает читабельность конечного loop()... и внезапно убедится что код оказался "не меньше". :)

Вам это будет не менее непонятно, а мне и не интересно ни разу.

P.P.S. Осталось решить совсем мелкую проблему: в случае, когда оба датчика срабатывают (почти) одновременно, лампы будут загораться с концов как и положено. Но вот по истечению паузы .. выключаться они будут с тех же самых концов к середине. А хотелось бы "не так" ..

Но. соберите и опубликуйте уже окончательный скетч, и мы эту проблему решим.

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

Ок, через недельку-месяцок, как разберусь во всем этом)))))))))) если смогу конечно)

Но чувствую что вряд ли :( 

Половину не пойму, что от куда взялось то :(

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

Уж не знаю, правильно или нет, но компилятор скушал :(


#define fadePin1 3       // пин управления MOSFET транзистором
#define fadePin2 5       // пин управления MOSFET транзистором
#define fadePin3 6       // пин управления MOSFET транзистором
#define fadePin4 9       // пин управления MOSFET транзистором
#define fadePin5 10       // пин управления MOSFET транзистором
#define fadePin6 11       // пин управления MOSFET транзистором

#define pirPin1 2         // пин подключения управляющего сигнала PIR датчика1
#define pirPin2 4         // пин подключения управляющего сигнала PIR датчика2

int calibrationTime = 30; // Время калибровки датчика (10-60 сек. по даташиту)

void setup()
{
  pinMode(pirPin1, INPUT);   // настариваем 2 пин как вход для сигналов с датчика
  pinMode(pirPin2, INPUT);   // настариваем 4 пин как вход для сигналов с датчика
  pinMode(fadePin1, OUTPUT); // пины на выход, для управления транзисотором
  pinMode(fadePin2, OUTPUT);
  pinMode(fadePin3, OUTPUT);
  pinMode(fadePin4, OUTPUT);
  pinMode(fadePin5, OUTPUT);
  pinMode(fadePin6, OUTPUT);
   
  Serial.begin(9600);
  Serial.print("Calibrating"); //дадим датчику время на калибровку
  for(int i = 0; i < calibrationTime; i++)
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

// структура - описание понятия "Лампа" - это пин и текущая яркость:
typedef struct{
  uint8_t pin;
  uint8_t bright;
} Led;

typedef struct{
  uint8_t        pir_pin;   // номер пина для датчика движения
  char           step;      // бывшая переменная isGo, теперь это "шаг" изменения яркости.
  uint8_t        lamp;      // номер текущей лампы, которой изменяем яркость
  char           max;       // номер последней лампы (недосчитывая) ДО которой будем перебирать лампы
  unsigned long  startedAt; // начало текущей паузы шага изменения лампы
} FadeCycle;

FadeCycle    fadeControl[2];

// теперь создадим список ламп, заодно и введем константу "всего ламп"
#define MAX_LED 6
Led  fades[MAX_LED] = {{fadePin1, 0}, {fadePin2, 0}, {fadePin3, 0},
                       {fadePin4, 0}, {fadePin5, 0}, {fadePin6, 0}};

#define WAIT_1  4          // 10мсек - пауза между изменениями яркости
uint32_t startedAt = 0;    // тут будем хранить время последнего запуска fadeLed
#define WAIT_PAUSE 5000    // пауза когда MAX_LED=255
uint32_t startedPause = 0; // тут будем вести отсчет паузы до выключения

//int8_t       isGo1 = 0; // режим включения/выключения от левого датчика
//uint8_t      lamp1 = 0; // номер текущей лампы управления левым датчиком
//uint8_t      max1 = 0;  // последний номер режимов левого датчика

//int8_t       isGo2 = 0; // режим включения/выключения от правого датчика
//uint8_t      lamp2 = 0; // номер текущей лампы управления правого датчиком
//uint8_t      max2 = 0;  // последний номер режимов правого датчика

uint8_t isDayNow(void){ return 0; }

/**
 * Функция изменения яркости на 1 шаг state РАЗ в 10 миллисекунд
 * @param state: +1 -- включение; -1 -- выключение
 */
void fadeLED(uint8_t num)
{
  Led * ptr = &(fades[fadeControl[num].lamp]);          // врем. лок. указатель на структуру "лампа"

  if(
     millis() - fadeControl[num].startedAt >= WAIT_1    // пора изменять яркость?
     && (
        (fadeControl[num].step==1 && ptr->bright < 255) // включаем И есть куда?
        ||
        (fadeControl[num].step==-1 && ptr->bright > 0)  // или вЫключаем И есть куда?
      )
  ){
      fadeControl[num].startedAt = millis();            // новое время для отсчета следующей паузы

      ptr->bright += fadeControl[num].step;             // изменяем яркость
      analogWrite( ptr->pin, ptr->bright);              // устанавливаем на выходе

      Serial.print(" b="); Serial.println(ptr->bright); // передаем данные в порт для отладки
  }
}

//uint32_t curTime;

void loop()

{
// if( isDayNow() ){ /*выключить всё*/ return; }

for(uint8_t num=0; num<2; num++)
{
  FadeCycle * cur = &(fadeControl[num]);

  if( digitalRead(cur->pir_pin) )
  {
    cur->step = 1;
    cur->lamp = (num==0? 0 : MAX_LED-1);
    cur->max  = (num==0? MAX_LED : -1);
  }
  if(
      (cur->step > 0)                                  // если включаем лампы, то сразу
      || (
           (cur->step < 0)                             // а вот если вЫключаем, то
           && (millis() - startedPause >= WAIT_PAUSE)  // по истечению паузы
        )
  ){
    if( cur->step > 0 && fades[cur->lamp].bright == 255 )
    {
      cur->lamp += (num==0? 1 : -1);
      if( cur->lamp == cur->max )
      {
        startedPause = millis();
        cur->step = -1;
        cur->lamp = (num==0? 0 : MAX_LED-1);
        cur->max = (num==0? MAX_LED : -1);
      }
    }else
      if( cur->step < 0 && fades[cur->lamp].bright == 0 )
      {
        cur->lamp += (num==0? 1 : -1);
        if( cur->lamp == cur->max )
        {
          cur->step = 0;
        }
      }else{
        fadeLED(num); // теперь сюда передаем номер группы!
      }
  }
}
}

Но судя по работе, не правильно! :(

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

Почти верно. Массив структур fadeControl у вас объявлен, и в нем поле pir_pin должно содержать номер того пина, на котором сидит датчик движения. Для 0 элемента массива это pirPin1, а для 1-го элемента это pirPin2 .. но они туда в setup не прописываются. Остальные параметры структуры можно и не задавать, они устанавливаются по мере необходимости. Но вот без номера пина, ваш digitalRead() читает из неизвестно откуда ..

Переставьте setup() ниже определения структур и данных и добавьте в него установку номеров пинов датчиков, типа так:

fadeControl[0].pir_pin = pirPin1;
fadeControl[1].pir_pin = pirPin2;

Остальное похоже на правду.

SOCHINEC
Offline
Зарегистрирован: 01.05.2016
// структура - описание понятия "Лампа" - это пин и текущая яркость:
typedef struct{
  uint8_t pin;
  uint8_t bright;
} Led;

typedef struct{
  uint8_t        pir_pin;   // номер пина для датчика движения
  char           step;      // бывшая переменная isGo, теперь это "шаг" изменения яркости.
  uint8_t        lamp;      // номер текущей лампы, которой изменяем яркость
  char           max;       // номер последней лампы (недосчитывая) ДО которой будем перебирать лампы
  unsigned long  startedAt; // начало текущей паузы шага изменения лампы
} FadeCycle;

FadeCycle   fadeControl[2];


void setup()
{ 
  fadeControl[0].pir_pin = pirPin1;
  fadeControl[1].pir_pin = pirPin2;
  
  pinMode(pirPin1, INPUT);   // настариваем 2 пин как вход для сигналов с датчика
  pinMode(pirPin2, INPUT);   // настариваем 4 пин как вход для сигналов с датчика
  pinMode(fadePin1, OUTPUT); // пины на выход, для управления транзисотором
  pinMode(fadePin2, OUTPUT);
  pinMode(fadePin3, OUTPUT);
  pinMode(fadePin4, OUTPUT);
  pinMode(fadePin5, OUTPUT);
  pinMode(fadePin6, OUTPUT);

Если я все верно понял, то вроде так!?

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

Пробую!

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

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

Там в целом должно быть "без разницы" первый или второй датчик. Попробуйте запустить цикл только по второму датчику поставив стартовое условие цикла i=1, то есть начинаем не с 0, а сразу с 1, пропуская первый датчик ..

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

Ну в общем-то, посмотрел .. всё "как обычно": поле lamp в структуре FadeCycle надо сделать char .. поскольку при обратном счете оно принимает значения 5,4,3,2,1,0, .. -1 . то есть является знаковым байтом. :)

SOCHINEC
Offline
Зарегистрирован: 01.05.2016
#define fadePin1 3       // пин управления MOSFET транзистором
#define fadePin2 5       // пин управления MOSFET транзистором
#define fadePin3 6       // пин управления MOSFET транзистором
#define fadePin4 9       // пин управления MOSFET транзистором
#define fadePin5 10       // пин управления MOSFET транзистором
#define fadePin6 11       // пин управления MOSFET транзистором

#define pirPin1 2         // пин подключения управляющего сигнала PIR датчика1
#define pirPin2 4         // пин подключения управляющего сигнала PIR датчика2

int calibrationTime = 30; // Время калибровки датчика (10-60 сек. по даташиту)

// структура - описание понятия "Лампа" - это пин и текущая яркость:
typedef struct{
  uint8_t pin;
  uint8_t bright;
} Led;

typedef struct{
  uint8_t        pir_pin;   // номер пина для датчика движения
  char           step;      // бывшая переменная isGo, теперь это "шаг" изменения яркости.
  char           lamp;      // номер текущей лампы, которой изменяем яркость
  char           max;       // номер последней лампы (недосчитывая) ДО которой будем перебирать лампы
  unsigned long  startedAt; // начало текущей паузы шага изменения лампы
} FadeCycle;

FadeCycle   fadeControl[2];


void setup()
{ 
  fadeControl[0].pir_pin = pirPin1;
  fadeControl[1].pir_pin = pirPin2;
  
  pinMode(pirPin1, INPUT);   // настариваем 2 пин как вход для сигналов с датчика
  pinMode(pirPin2, INPUT);   // настариваем 4 пин как вход для сигналов с датчика
  pinMode(fadePin1, OUTPUT); // пины на выход, для управления транзисотором
  pinMode(fadePin2, OUTPUT);
  pinMode(fadePin3, OUTPUT);
  pinMode(fadePin4, OUTPUT);
  pinMode(fadePin5, OUTPUT);
  pinMode(fadePin6, OUTPUT);
   
  Serial.begin(9600);
  Serial.print("Calibrating"); //дадим датчику время на калибровку
  for(int i = 0; i < calibrationTime; i++)
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}
 


// теперь создадим список ламп, заодно и введем константу "всего ламп"
#define MAX_LED 6
Led  fades[MAX_LED] = {{fadePin1, 0}, {fadePin2, 0}, {fadePin3, 0},
                       {fadePin4, 0}, {fadePin5, 0}, {fadePin6, 0}};

#define WAIT_1  4  // 10мсек - пауза между изменениями яркости
uint32_t startedAt = 0;    // тут будем хранить время последнего запуска fadeLed
#define WAIT_PAUSE 5000    // пауза когда MAX_LED=255
uint32_t startedPause = 0; // тут будем вести отсчет паузы до выключения

//int8_t       isGo1 = 0; // режим включения/выключения от левого датчика
//uint8_t      lamp1 = 0; // номер текущей лампы управления левым датчиком
//uint8_t      max1 = 0;  // последний номер режимов левого датчика

//int8_t       isGo2 = 0; // режим включения/выключения от правого датчика
//uint8_t      lamp2 = 0; // номер текущей лампы управления правого датчиком
//uint8_t      max2 = 0;  // последний номер режимов правого датчика

uint8_t isDayNow(void){ return 0; }



/**
 * Функция изменения яркости на 1 шаг state РАЗ в 10 миллисекунд
 * @param state: +1 -- включение; -1 -- выключение
 */
void fadeLED(uint8_t num)
{
  Led * ptr = &(fades[fadeControl[num].lamp]);          // врем. лок. указатель на структуру "лампа"

  if(
     millis() - fadeControl[num].startedAt >= WAIT_1    // пора изменять яркость?
     && (
        (fadeControl[num].step==1 && ptr->bright < 255) // включаем И есть куда?
        ||
        (fadeControl[num].step==-1 && ptr->bright > 0)  // или вЫключаем И есть куда?
      )
  ){
      fadeControl[num].startedAt = millis();            // новое время для отсчета следующей паузы

      ptr->bright += fadeControl[num].step;             // изменяем яркость
      analogWrite( ptr->pin, ptr->bright);              // устанавливаем на выходе

      Serial.print(" b="); Serial.println(ptr->bright); // передаем данные в порт для отладки
  }
}

//uint32_t curTime;

void loop()

{
// if( isDayNow() ){ /*выключить всё*/ return; }

for(uint8_t num=0; num<2; num++)
{
  FadeCycle * cur = &(fadeControl[num]);

  if( digitalRead(cur->pir_pin) )
  {
    cur->step = 1;
    cur->lamp = (num==0? 0 : MAX_LED-1);
    cur->max  = (num==0? MAX_LED : -1);
  }
  if(
      (cur->step > 0)                                  // если включаем лампы, то сразу
      || (
           (cur->step < 0)                             // а вот если вЫключаем, то
           && (millis() - startedPause >= WAIT_PAUSE)  // по истечению паузы
        )
  ){
    if( cur->step > 0 && fades[cur->lamp].bright == 255 )
    {
      cur->lamp += (num==0? 1 : -1);
      if( cur->lamp == cur->max )
      {
        startedPause = millis();
        cur->step = -1;
        cur->lamp = (num==0? 0 : MAX_LED-1);
        cur->max = (num==0? MAX_LED : -1);
      }
    }else
      if( cur->step < 0 && fades[cur->lamp].bright == 0 )
      {
        cur->lamp += (num==0? 1 : -1);
        if( cur->lamp == cur->max )
        {
          cur->step = 0;
        }
      }else{
        fadeLED(num); // теперь сюда передаем номер группы!
      }
  }
}
}

Вот ОН, рабочий скетч! ;) Мож кому сгодится! :)

#define WAIT_1  4  // 10мсек - пауза между изменениями яркости это понятно что! А где храниться переменная самой яркости, вот это понять не могу! Подскажите, как её поменять и где!?

Одно смущает, когда от двух датчиков сразу, красивее было бы тушить от центра к краям! Но и так красява:) Теперь все это в железо и куууууууучу проводов:)

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

Текущие яркости хранятся в поле bright структуры описания "лампа", для каждой лампы - в своем элементе массива fades[]

Да. Вам осталось сделать чтобы когда оба датчика сработали, то гашение ламп должно начинаться не "так же", а от точки их всртечи .. чем таким особенным (как обычно, все интересное в отличиях, а не общностях!) отличается поведение нашего алгоритма?

Смотрите на код: "if( cur->step > 0 && fades[cur->lamp].bright == 255 )" строка 129. Если шаг больше нуля (кстати стоит везде заменить на больше/меньше вместо ==, тогда можно будет изменять яркость не по +-1), то есть если мы включали лампу И(!) её яркость достигла предела .. в следующей строке идет попытка перейти на следующую лампу .. но она УЖЕ может быть включена вторым датчиком .. нет? Кем-то ишо? :)

Соответственно, если после 131 строки с попыткой перехода поставить проверку на текущую яркость лампы .. и если мы тут обнаруживаем что она включена .. то эта лампа и будет той самой "точкой отсчета" при последующем выключении. Нет? :)

А если да, то что надо сделать в этом случае?

P.S. И заметьте, что при обработке алгоритма второго датчика произойдет "то же самое" .. он тоже обнаружит что лампа "уже включена".. сам.
 

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

Пока оставим так как есть!:)

Вот нашел еще косячек!

Сработали оба датчика, включили, все в норме. Но стоит сработать какому либо одному датчику(когда считаем паузу) после паузы, тухнет только одна лампа, первая, в зависимости от того какой датчик сработал! 

И потом 5 ламп горят(ну тут понятно, горят то 5, а не шесть, соответственно паузу считать мы не можем), до того как не сработает какой нибудь датчик!

Вроде понятно пояснил:)

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

Вроде бы не должно быть такого косячка. Когда датчики отработали, управлялки установлены в step=-1, и последний сработавший датчик перезапустит паузу. Во время неё, исполняется код в цикле по очереди для обоих датчиков, строки: 116 (проверка датчиков), 123 - "мимо", ждем выключения ИЛИ (далее) 125 - "ок", будем выключать И 126 - "мимо", пауза ещё НЕ завершена. Всё.

Если один из дачиков в этом наборе сработает (строка 116), то он переведет себя на режим включения ламп, и далее сразу же (в этом же проходе цикла) сработает строка 123 и сразу далее строка 129 тоже сработает (лампы - горят) и сразу сработает переключение на следующую лампу, строка 131. Это всё за один проход цикла, как только обнаружено срабатывание. Далее, если пауза так и не успеет отработать, за каждый следующий вызов loop(), сработавший датчик будет переходить к следующей лампе, пока не переберет все, строкой 131. Псоле чего, отработает строка 132 и он перезапустит паузу заново, перейдя в режим выключения. То есть, если в прочессе пробежки в попытках включить лампу пауза не успела сработать для второго датчика, то никаких "косяков" вы не сможете заметить .. только лампы будут гореть ещё туже самую паузу.

Проверить можно так: запустили оба процесса "практически" одновременно - лампы должны загораться с обоих концов. С момента включения последней лампы засекаете время ожидания выключения и пока оно не завершено - запускаете один из датчиков повторно. Он "пробежится" ну, очень быстро и соответственно, с момента повторного срабатывания должна отработать пауза ещё раз и оба канал погаснуть со своих концов к середине. Так?

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

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

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

SOCHINEC
Offline
Зарегистрирован: 01.05.2016
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158
 b=159
 b=158

Это как раз и есть "Битва за лампу"

:)

это может быть на всех лампах, если они втретяться!

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

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

1. Активизация цикла включения ламп может останавливать выключение вторым процессом. После строки 120 последней версии "вот он рабочий скетч" добавить проверку:

if( fadeControl[1-num].step < 0 ){ fadeControl[1-num].step = 0; }

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

2. Процесс включения важнее процесса выключения, и можно в выключающую ветку вставить контроль "пересечения процессов" для остановки процесса выключения. Для этого надо менять строку 140:

// if( cur->step < 0 && fades[cur->lamp].bright == 0 )

if( cur->step < 0 ){
  if( fadeControl[1-num].step > 0 && cur->lamp == fadeControl[1-num].lamp ){
    cur->step = 0;
  }
  if( fades[cur->lamp].bright == 0 )

И соответственно добавить } перед строкой 150.

3. Можно не трогать процесс выключения, а всего лишь запретить паузу .. по истечении которой он продолжит свое выключение с той лампы, где стопорнулся. Для этого после строки 120 можно добавить типа так:

startedPause = millis()+5000;

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

.. и ещё несколько вариаций. :)

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

Пока воспользовался 1 вариантом! Вроде норма! Но на макете уже не понятно что да как, начал монтаж "Царской дороги" :)

Буду добивать на месте, с ноута потом ;)

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

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

С Вас "окончательный" скетч в сборе, может кому и понадобится. :)

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

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

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

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

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

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

"вошел - включилось, постоял внутри .. упс, пошло выключение"

"вошел - включилось, прошел - на выходе сработал .. второй датчик .. и упс. выключение пошло от него, а не от первого .. или от ОБОИХ"

и т.д. :)

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

Да, надо помозговать! :) 

Потестил, вообщем так:

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

Да, как то что то не то:(

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

Arhat109-2 пишет:

 

"вошел - включилось, постоял внутри .. упс, пошло выключение"

 

Для этого и есть пауза! она будет минуты 3 я так думаю!

А если долго надо, будет обычный выключатель!

Но это особо и не надо, это больше для красоты, чем для освещения! Но видно будет куды ступать, и хорошо!:)

 

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

Может это обойти так?

 Прошли первый, включилось если ВСЁ, то 2 датчик ТОЛЬКО продливает паузу(зачем нам что то включать, уже все горит, от своего датчика, пусть и горит дальше себе), не включает ничего!(так можно вообще?)

А вот если не все включилось еще, то включать со своей стороны!(Но я думаю редкое явление, не такое у меня тут движение:))

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

Но и тут 1000% будут косяки, я их просто не вижу:(

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

Я же предлагал Вам в самом начале "игнорировать" второй датчик на конец прохода того, кто "задел" первый .. иначе на выходе как раз получите именно этот эффект .. но! Если его игнорировать то .. а вдруг это и не выход из под второго датчика, а вход нового, как "отличить"? .. у вас там таких "коллизий" вагон и маленькая тележка .. расслабьтесь. С только 2-я датчиками движения можно оставить "как есть", ибо попытки избежать коллизии одного вида неизбежно приведут к друцгим. :)

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

Да я понимаю, что вагон, но хотя-бы чуть до ума бы довести :(

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

В таком разе, поперву сформулируйте ваше "до ума" ясно, четко .. в виде некоего автомата, лучше в ДРАКОН-схеме. Тогда вам станет совершенно понятно что и куда надо будет поправить в этом скетче. А так .. гадать можно до бесконечности.

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

Так вопрос так и остался открытым, так вообще возможно или нет!

Когда идет пауза, только продливать паузу, а не проходить по лампам?

(У нас же получается что мы пробегаем всю ветку, и приходим опять к паузе. Правильно?)

Это я думаю решит проблему! Или нет?

Пораскинул мозгами, потестил, все возможные варианты прохода датчиков (инопланетное вторжение не учел:)) думаю все таки это поможет!

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

Arhat109-2 пишет:

 лучше в ДРАКОН-схеме

Разрисовал уж целый блокнот :)

Что то просто не получается учесть, если не делать тесты!

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

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

На том сайте, что я Вам указывал есть несколько программ-редакторов ДРАКОН-схем. Есть платные с месяцем бесплатного пользования (ИС ДРАКОН) есть и бесплатные. Они заодно ещё и проверяют вашу схему на корректность, а то и вовсе не позволяют писать криво. Кроме того, там есть "кодогенерация" по схеме .. больше конечно ручная, но позволяет тем не менее получать вполне приемлемый код скетчей.

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

ну так если идет пауза, они и так включены! Тогда датчики перестанут руководить лампами, на время паузы, а будут только продливать паузу! (по логике мыслю! :)) !?

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

Arhat109-2 пишет:

Можно и не пробегать. Просто предварительно проверять условие "ещё идет пауза?" .. но какой в этом специальный смысл? 

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

Еще не разобрался в программе, но что то типо так!

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

Бред конечно составил :(

Так вроде логичнее!

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

Там есть кнопочка "проверить схему" - пользовались? Левых обратных стрелок (у Вас первая по схеме) быть не может согласно правилам. Это конечно же "не та схема".. давайте вечерком выложу свою.

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

Да я понимаю(надо не стрелку, а просто обойти датчик 1 в этой ветке), пока не разобрался еще! Пользовался проверкой, но видимо еще не понял что куда там, вечно пишет что должен быть "хотя бы один выход",  а зачем он мне, если этот цикл бесконечный?

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

в голове оно как то проще :)

Вот я как думаю;

1) датчик  сработал, все включил(запомнили что и кто включил и от куда), пошла пауза

2) пауза - опять движение - пауза ++

3) двежуха закончилась, гости свалили :) 

    прошла пауза(мы же помним что и кто и откуда включал ) вот и выключаем согласно самой первой сработки датчика(ов)

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

Не могу открыть ИС Дракон, похоже триальный период кончился .. ладно, давайте по вашей схеме из #241:

1. Вообще-то выход у Вас есть, поскольку это loop() вызывается бесконечно, а сам он очень даже конечен. Ну да ладно, пока можно и так.

2. Ветка "Датчик света" .. с чего это она у вас замыкается "сама на себя"? Она должна указывать вниз на маркер "Датчик света" .. и ветвление надо поменять местами, ибо "царская дорога" - прямая линия. После смены условия, выбор "нет" окажется справа и тоже должен уходить вниз схемы на маркер "Датчик1"

3. Ветка "Датчик1" .. какова его "Царская дорога"? Да и вообще, что он делает? Он ведь если НЕ сработал, то НЕ делает ничего .. то есть уходит на "Датчик2", а если сработал .. то только устанавливает режим включения ламп присваивая переменные .. и только. А стало быть когда "да", то есть одна, простая икона "Действие" с присвоением значений и .. маркер отсутствующей ветки "Включение".

4. Ветка "Включение" - вовсе не в хвосте действий датчика1, а самостоятельная ветка. И она у вас отрабатывает ровно 1 раз за 1 вызов loop() увеличивая яркость текущей лампы на ".step"

.. и т.д.

В целом, тут надо было применить не "Силуэт" а "Конечный автомат" .. но давайте уже на этом варианте доделаем.

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

Ну я так понимаю, что должно быть на много больше веток!?

1.датчик света

2.датчик 1

3.датчик 2

4.включение

5.выключение

6.пауза

Как минимум, хотя может я и ошибаюсь!

Кстати я ИС Дракон что то не понял вообще! :(

Эта программка мне больше понравилась, и вроде бесплатная! ;)

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

Да не проблема, кинуть автору денег. Он того заслуживает, да и дитё юзает.. Просто как обычно: "зима снова наступила неожиданно". :)

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

а сколько стоит? я что то не нашел!

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

Я на правильном пути?

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

Стоит в пределах 500руб. :)

Да, примерно так и должно быть. Сравните с кодом: если первый датчик не сработал, то по сути цикл по датчикам - завершается и переходим ко второму датчику. Давайте я завтра проплачу эти большие деньги и таки сделаю. "ИС Дракон" сразу "не позволяет писать криво" в отличии от Drakon-Editor, который по сути просто рисовалка произвольных схем.