Непонятная работа millis()

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Вообще-то не уверен, в программировании или в железе спрашивать надо... Простите, если что.

Значит, с delay() наигрался, сел изучать millis(). Накатал первый скетч:

int timeout=1000;
unsigned long nextmove;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
nextmove = millis()+timeout;
}

void loop() {
  // put your main code here, to run repeatedly:
int currenttime = millis();
if (currenttime >= nextmove)
{
   Serial.print(nextmove);
   Serial.println(" milliseconds passed; ");
   nextmove=currenttime + timeout; 
}
}

Открываю монитор порта и вижу вот такое:

Вот такие миллисекунды

 

 

 

 

 

 

Ну и, собственно, это что? Китайская железяка так себя ведет, или это секретная фишка такая?

Заранее спасибо за ответы.

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

Tollmuch пишет:

Ну и, собственно, это что? Китайская железяка так себя ведет, или это секретная фишка такая?

обычное дело - китайцы миллис палёный прошили в контроллер.

рекомендую пользоваться российскими контроллерами - там всё по ГОСТу. О_О

*int currenttime = millis();

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

Угу. millis() он большой в маленький холодильник int не помещается. Нужен большой двухкамерный unsigned long .

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

qwone пишет:

Угу. millis() он большой в маленький холодильник int не помещается. 

если свернуть в рулон, то помешается и в bool

Tollmuch
Offline
Зарегистрирован: 20.02.2018

qwone пишет:

Угу. millis() он большой в маленький холодильник int не помещается. Нужен большой двухкамерный unsigned long .

Ну между прочим в моем крутом коде натурально unsigned long :)

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Tollmuch пишет:

Ну между прочим в моем крутом коде натурально unsigned long :)

В одном месте. А во втором - int. Код у тебя не крутой, а так - в мешочек :)

ЗЫРЬ СТРОКУ 12!!!

Tollmuch
Offline
Зарегистрирован: 20.02.2018

А. Понял. Спасибо :)

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

Tollmuch пишет:

Ну между прочим в моем крутом коде натурально unsigned long :)

вместо выепываться - перечитал бы свой код: int currenttime = millis();

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Все, все, не пинайте сильно :D Спасибо!

Logik
Offline
Зарегистрирован: 05.08.2014

Какое спасибо! А где вопрос про переполнение и борьбу с ним?

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

и, вдогонку - вот это nextmove=currenttime + timeout; не переживёт переполнения миллис.

кури пример Мигаем светодиодом без delay()

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Покурил,  спасибо :) Заодно и эту http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis, правда, не уверен, что все правильно понял, но что сложение - это плохо, уже, буду надеяться, усвоил :)

 

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

Tollmuch пишет:
Китайская железяка так себя ведет

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

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Да уж. Выступил :/
 

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

Кстати, раз уж Вы поняли про переполнение, чего не исправили свой код? Или исправили, просто сюда не выложили?

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Исправил, да. Думал, чего ж людям голову морочить...  В общем, задача у меня вполне конкретная (и, собственно, вряд ли я буду в тему ардуино дальше вгрызаться, пока/если не появится новое непреодолимое желание :) ) - организовать подсветку в пруду на даче. Должны быть две группы по два RGB-прожектора, которые бы тупо переливались в классическом порядке перебора цветов (красный-оранжевый-желтый-зеленый-голубой-синий-фиолетовый-белый) с разной скоростью (на одной группе - медленно, на другой - очень медленно, фонари не должны притягивать взгляд динамикой вот этого перелива, но цвет таки должен меняться). В идеале было бы круто, если бы скорость можно было менять с радиопульта, но можно и обойтись. 

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

На данный момент сумел сделать управление ШИМ через millis() на один канал, правда, цикл выглядит по-дурацки, но я пока millis() же ковырял :) Странная формула для PWM - c Вашей же, ЕвгенийП, подсказки, постарался осмыслить статью про нелинейную регулировку яркости http://radiolaba.ru/polezno-znat/regulirovka-yarkosti-svetodioda.html. Работает нормально, но значения ШИМ меньше 1, как выяснилось, к включению светодиода не приводят, поэтому там диапазон ограничен 16-100.


#define PWMPin 9

int timeout=100;
float PWM;
int i=16;
unsigned long pasttime=0;

void setup() {
pinMode(PWMPin, OUTPUT);
}

void loop() {

while (i<100)
{
  unsigned long currenttime = millis();
     if (currenttime - pasttime >= timeout)
    {
        PWM = pow(i / 16.06, 1 / 0.33);
        analogWrite(PWMPin, PWM);
        pasttime=currenttime; 
        i++;
      }
}
while (i>16)
{
    unsigned long currenttime = millis();
    if (currenttime - pasttime >= timeout)
      {
        PWM = pow(i / 16.06, 1 / 0.33);
        analogWrite(PWMPin, PWM);
        pasttime=currenttime; 
        i--;
      }
}
}
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Tollmuch пишет:
В общем, задача у меня вполне конкретная (и, собственно, вряд ли я буду в тему ардуино дальше вгрызаться, пока/если не появится новое непреодолимое желание :) ) - организовать подсветку в пруду на даче. Должны быть две группы по два RGB-прожектора, которые бы тупо переливались в классическом порядке перебора цветов (красный-оранжевый-желтый-зеленый-голубой-синий-фиолетовый-белый) с разной скоростью (на одной группе - медленно, на другой - очень медленно, фонари не должны притягивать взгляд динамикой вот этого перелива, но цвет таки должен меняться). В идеале было бы круто, если бы скорость можно было менять с радиопульта, но можно и обойтись.
Задача решается в лет с помощью цифрового автомата. Но надо знать основы программирования, которые даже не синтаксис языка. 

Tollmuch
Offline
Зарегистрирован: 20.02.2018

qwone пишет:

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

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

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

Не , не получится . Это как решение квадратного уровнения. Вроде просто. Но этому надо научиться. А вы "решение крадратного уровнения подбираете на ощуп с некоторой погрешностью"(разумеется это аналогия).

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Да, примерно так все и происходит. Но пока что есть ощущение, что прикладную задачу решить рано или поздно получится. Посмотрим, может, оно пройдет в процессе :)

GarryC
Offline
Зарегистрирован: 08.08.2016

Позволю себе предложить Вам следующие простые правки :


#define PWMPin 9

void setup() {
pinMode(PWMPin, OUTPUT);
}

void loop() {
int timeout=100;
float PWM;
unsigned long pasttime=0;
byte i=16;
byte di=1;

while (1) {
    unsigned long currenttime = millis();
     if (currenttime - pasttime >= timeout) {
        PWM = pow(i / 16.06, 1 / 0.33);
        analogWrite(PWMPin, PWM);
        pasttime=currenttime; 
        i=i+di;
        if ((i==99) || (i==17)) di=0-di;
      }
}

 

Кстати, Вы уверены, что 16 и 100 выдавать не надо ?

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Клапауций 555 пишет:

и, вдогонку - вот это nextmove=currenttime + timeout; не переживёт переполнения миллис.

кури пример Мигаем светодиодом без delay()

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

Tollmuch
Offline
Зарегистрирован: 20.02.2018

GarryC, спасибо большое, мне только это осознать надо будет на досуге :) 

С первого взгляда вот это не понял: 

while (1) 

Это просто бесконечный цикл?

Насчет 16 и 100 - я думал, что они будут как раз выдаваться последней итерацией в цикле? 

А если переменные объявлять за пределами loop(), тогда в цикле же вообще необходимости нет? 

 

Tollmuch
Offline
Зарегистрирован: 20.02.2018

GarryC, спасибо за подсказку и изящное решение. Я, надо сказать, добился того же результата, но по сравнению с Вашим циклом совершенно трансанально :) Единственное что, если i объявлять равным 16, то вот тут "if ((i==99) || (i==17)) di=0-di;" тоже надо "if ((i==99) || (i==16)) di=0-di;", иначе цикл на втором шаге сбивается и начинает творить полную хрень. 

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

Получилось вот так:

#define PWMPin1 9
#define PWMPin2 10

int timeout1=20;
int timeout2=100;
float PWM1;
float PWM2;
byte i1=16;
byte i2=16;
byte di1=1;
byte di2=1;
unsigned long pasttime1=0;
unsigned long pasttime2=0;

void setup() {
pinMode(PWMPin1, OUTPUT);
pinMode(PWMPin2, OUTPUT);
}

void loop() {

 unsigned long currenttime1 = millis();
 unsigned long currenttime2 = millis();
     
 if (currenttime1 - pasttime1 >= timeout1) {
    PWM1 = pow(i1 / 16.06, 1 / 0.33);
    analogWrite(PWMPin1, PWM1);
    pasttime1=currenttime1;
    i1=i1+di1;
    if ((i1==100) || (i1==16)) di1=0-di1;
  }

  if (currenttime2 - pasttime2 >= timeout2) {
    PWM2 = pow(i2 / 16.06, 1 / 0.33);
    analogWrite(PWMPin2, PWM2);
    pasttime2=currenttime2;
    i2=i2+di2;
    if ((i2==100) || (i2==16)) di2=0-di2;
  }
}

Еще раз спасибо! Дальше буду RGB пилить.

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

Жесть 

22  unsigned long currenttime1 = millis();
23  unsigned long currenttime2 = millis();

Может одним обойдетесь.

12 unsigned long pasttime1=0;
13 unsigned long pasttime2=0;

А это правильно.

Tollmuch
Offline
Зарегистрирован: 20.02.2018

qwone, ну да. Наверно, обойдусь :) Спасибо.

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

qwone пишет:

Может одним обойдетесь.

Ничо-ничо! Запас он карман не тянет! :)

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

Ну тогда еще в карман

и в код

enum {sInit = 0, sOff, sRed, sOrange, sYellow, sGreen, sSky, sBlue, sViolet, sWhite};

 

Tollmuch
Offline
Зарегистрирован: 20.02.2018

qwone, спасибо. Это меня надолго заткнет :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Пух, привыкай использовать enum правильно, пора. 

enum class enumColor: byte  {Init = 0, Off, Red, Orange, Yellow, Green, Sky, Blue, Violet, White};

обращаться потом, кашеш, сложнее:

   enumColor color = enumColor::Green;   

зато имена внутри enum-ов наружу не светят и не пересекаются с глобальными именами. 

А просто enum имеет смысл применять только когда нужны именованные константы.

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

Нашел откуда взялась такая странная вещественная арифметика для ШИМ. Там даже в статье сказано верно: заранее рассчитанные таблицы заполнения ШИМ. Округлите ШИМ до целого и сложите в программную память 1 раз для всех светодиодов. Оно ещё и места меньше займет и куда как ползеней будет.

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

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

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

/* цифровой автомат*/
unsigned long mill;
//--------------------------------
const unsigned long interval = 1000;
enum {sInit = 0, sOff, sRed, sOrange, sYellow, sGreen, sSky, sBlue, sViolet, sWhite};
unsigned long past;
byte state;
void stand(byte s) {
  state = s;
  past = mill;
  switch (state) {
    case sInit:
      /*  проинициализировать выводы*/
      state = sOff;
    /*break; здесь убрать*/
    case sOff:
      /*  выключить*/
      break;
    case sRed:
      /*  включить красный*/
      break;
    case sOrange:
      /*  включить оранжевый*/
      break;
    case sYellow:
      /*  включить желтый*/
      break;
    case sGreen:
      /*  включить зеленый*/
      break;
    case sSky:
      /*  включить голубой*/
      break;
    case sBlue:
      /*  включить синий*/
      break;
    case  sViolet:
      /*  включить фиолетовый*/
      break;
    case sWhite:
      /*  включить белый*/
      break;
  }
}
void unitRun() {/*вставить в lojp*/
  if (state == sRed    && mill - past >= interval) stand(sOrange);
  if (state == sOrange && mill - past >= interval) stand(sYellow);
  if (state == sYellow && mill - past >= interval) stand(sGreen);
  if (state == sGreen  && mill - past >= interval) stand(sSky);
  if (state == sSky    && mill - past >= interval) stand(sBlue);
  if (state == sBlue   && mill - past >= interval) stand(sViolet);
  if (state == sViolet && mill - past >= interval) stand(sWhite);
  if (state == sWhite  && mill - past >= interval) stand(sRed);
}
//-----------------------------
//----main()------------------------
void setup() {
  stand(sInit);/*проинициализировать*/
  stand(sRed);/*запустить цепочку начиная с красного*/
}

void loop() {
  mill = millis();
  unitRun();
}
/*Скетч использует 1218 байт (3%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 18 байт (0%) динамической памяти, оставляя 2030 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Форум слегка вырос, что несомненно радует. Когда я тут два года назад между путешествием на пляж заяснял что такое конченный автомат и как его можно обобщенно реализовать для управления МК - меня тут многие, что теперь "гуру" поднимали насмех от непонимания вопросу. Спасибо, повеселили. Это первое что им дается ещё с "вумным светофором" и без delay().

Было как-то так: http://arduino.ru/forum/programmirovanie/novichkam-avtomatnoe-programmir...

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

Arhat109-2, а еще лучше научить детишек не "засирать" loop() "грязью". А всю грязь выносить в отдельные функции. Так же делать с setup()

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

В конечном варианте там и нет ничего кроме набора исполнителей конечных автоматов, типа так:

TscControl tscLed;      // глобальная обьява конечного автомата "светофор из трех светодиодов"
TscControl tscIRsensor; // аналогично для датчика подхода пешеходов к светофору.
TscControl tscStopper;  // серва, что рулит шлакбаумом для машинок.

void loop()
{
  tscLed.run();
  tscIRsensor.run();
  tscStopper.run();
}

Собственно это и есть весь луп. :) Все остальное прописывается в таблицах состояний и функций переходов.

Там тоже все строго по задаче:

"Светофор переключает "красный", "Желтый" и "Зеленый" сигналы по времени и по порядку. При этом, Зеленый перед выключением мигает 3 раза. Состояния светофора для авто: "красный-вкл" - 30сек, "желтый вкл" - 2сек, "зеленый вкл" - 30сек, макро "мигалка": ("зеленый выкл" - 0.5сек, "зеленый вкл" - 0.5сек) х 2 раза. При включенном одном цвете остальные - выключены. Состояние "Желтый" переводит автомат "датчик пешеходов" в состояние счет, если тот был в состоянии "ожидание включения". Состояние светофора "красный" - опускает шлакбаум. состояние светофора "зеленый" поднимает шлакбаум.

Датчик пешеходов имеет состояния: "Выключен" - 45сек, "Ожидание включения" - без ограничения времени, "Счет". Если в состоянии "счет", к светофору скопилось 5 и более пешеходов, то датчик переводит светофор в режим мигания зеленым (меняет состояние автомата "светофор") сразу после срабатывания. И сам переходит в состояние "выключен" и затем в состояние "ожидание включения".

Автомат шлакбаум или "закрыть" или "открыть" или "без изменений". Всего три состояния. Управляется извне, другими автоматами.

.. вот, берем это "ТЗ" и тупо пишем таблицы состояний, функции исполнения состояния и .. а всё. Остальное уже есть готовое. :)

Как показала практика - одного трехчасового занятия (при начальном знании языка) вполне достаточно для написания, освоения и даже на поиграть время остается навалом. Сейчас пробую при ПОЛНОМ незнании языка дать одновременно с языком. Правда только "С" версию .. сложнее, уже третье занятие пойдет на выходных. Но, тоже проблемы больше не в конечных автоматах, а в правилах самого языка, которые приходится давать постепенно в два-три захода, начиная с "тут пишем волшебное слово..", потом "да, и тут и вообще везде оно пишется так.." и только потом "это - синтаксическое правило ..". :)

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

В целом, при небольших функциях управления автоматами (менее 1мсек), такой код на Мега2560 вполне тянет до 100 управляемых устройств с вполне нормальным средним временем реакции в пределах 0.1 секунды. Проверено.

Точно также, наша "машинка по линии" .. есть вариант на полностью "автоматном" программировании и она в цикл 2мсек укладывается "только так", несмотря на то что замеряет по 3 раза все 5-7 датчиков линии обыкновенным analogRead() .. а то ту всё пид-да-пид нужен .. нафига? :)

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

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

Arhat109-2 пишет:

Было как-то так: http://arduino.ru/forum/programmirovanie/novichkam-avtomatnoe-programmir...

Просмотрел. Последнее сообщение вставило нипадецки! По этому поводу нам пора заводить что-то вроде лурковского "правила №34".

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

Ну .. там оно как раз к месту. Во всем примере была использована неверная обработка интервалов через millis(). Ничто конечно не мешает переварить пример верно, но .. :)

Tollmuch
Offline
Зарегистрирован: 20.02.2018

qwone, силюсь понять, а что вот в этом случае значит "проинициализировать выводы"? Объявить пины и задать PinMode? Или что-то еще? 

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Да, и кстати вот - меня тоже с момента прочтения статьи про нелинейную регулировку яркости вяло так интересовало, действительно ли analog.Write() передает на пин дробные значения? Но поскольку визуально все устраивает, то спросить так и не собрался - до сих пор :) 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Tollmuch, а какие параметры у функции analog.Write?

Tollmuch
Offline
Зарегистрирован: 20.02.2018

DetSimen,

 

17         PWM = pow(i / 16.06, 1 / 0.33);
18         analogWrite(PWMPin, PWM);

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

Tollmuch
Offline
Зарегистрирован: 20.02.2018

А в каких-то других случаях может дробное значение передаваться?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

тип параметров функции прописан в ее обьявлении. Ничего другого туда не передашь. 

еще можно почитать про overloaded functions C++ и написать самому. 

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

Tollmuch пишет:

А в каких-то других случаях может дробное значение передаваться?

Там стоит счтёчик который тикает. Параметр analogRead - количество тиков, которые надо отсчитать.

А теперь сами ответьте - есть смыл старать впихнуть ему дробное знаение? Он что, два с половиной тика отсчитает?

Tollmuch
Offline
Зарегистрирован: 20.02.2018

ЕвгенийП, нет, конечно. Но в принудительном округлении (на моей конкретной задаче :) ) тоже, наверно, смысла нет, раз "оно само"?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Само оно отбрасывает дробную часть. Например 1,999999 - получится 1. Если хочешь окрулять до ближайшего, то передавай типа f+0.5 - тогда будет само округлять до ближайшего к f целого

Tollmuch
Offline
Зарегистрирован: 20.02.2018

Ну вот. Взял я изящный, аккуратный код уважаемого qwone и опять сделал из него чего-то некрасивое. Правда, работает. На одну группу пока. Интервал коротенький в тестовых целях. 

/* цифровой автомат*/
#define PWMPinRed 9
#define PWMPinGreen 10
#define PWMPinBlue 11

unsigned long mill;

//--------------------------------

const unsigned long interval = 10;
const byte GAIN = 1;
const byte FADE = -1;
enum {sInit = 0, sRed, sYellow, sGreen, sCyan, sBlue, sViolet, sWhite, sLoop};
unsigned long past;
byte state;
float PWM;
byte iRed;
byte iGreen;
byte iBlue;

void stand(byte s) {
  state = s;
  past = mill;
  switch (state) {

     case sInit:
     state = sRed;
     
     case sRed:
/*  включить красный*/
      if (iRed < 100) {
        PWM = pow(iRed / 16.06, 1 / 0.33);
        analogWrite(PWMPinRed, PWM);
        iRed = iRed+GAIN;
      }
     break;

     case sYellow:
/*  включить желтый*/
      if (iGreen < 100) {
        PWM = pow(iGreen / 16.06, 1 / 0.33);
        analogWrite(PWMPinGreen, PWM);
        iGreen=iGreen+GAIN;
      }
     break;

    case sGreen:
/*  включить зеленый*/
      if (iRed > 15) {
        PWM = pow(iRed / 16.06, 1 / 0.33);
        analogWrite(PWMPinRed, PWM);
        iRed=iRed+FADE;
      }  
     break;

    case sCyan:
/*  включить голубой*/
      if (iBlue < 100) {
        PWM = pow(iBlue / 16.06, 1 / 0.33);
        analogWrite(PWMPinBlue, PWM);
        iBlue=iBlue+GAIN;
      }
     break;

    case sBlue:
/*  включить синий*/
      if (iGreen > 15) {
        PWM = pow(iGreen / 16.06, 1 / 0.33);
        analogWrite(PWMPinGreen, PWM);
        iGreen=iGreen+FADE;
      }
     break;

    case  sViolet:
/*  включить фиолетовый*/
      if (iRed < 100) {
        PWM = pow(iRed / 16.06, 1 / 0.33);
        analogWrite(PWMPinRed, PWM);
        iRed=iRed+GAIN;
      }
     break;

    case sWhite:
/*  включить белый*/
      if (iGreen < 100) {
        PWM = pow(iGreen / 16.06, 1 / 0.33);
        analogWrite(PWMPinGreen, PWM);
        iGreen=iGreen+GAIN;
      }
     break;

    case sLoop:
/*  выключить все*/
      if (iGreen > 15 && iBlue > 15 && iRed > 15) {
        PWM = pow(iGreen / 16.06, 1 / 0.33);
        analogWrite(PWMPinRed, PWM);
        analogWrite(PWMPinGreen, PWM);
        analogWrite(PWMPinBlue, PWM);
        iRed=iRed+FADE;
        iGreen=iGreen+FADE;
        iBlue=iBlue+FADE;
      }
     break;
  }

}

void unitRun() {/*вставить в lojp*/

  if (state == sRed && iRed < 100 && mill - past >= interval){
    stand(sRed);
  }
  else if (state == sRed && iRed == 100 && mill - past >= interval) {
    stand(sYellow);
  }
  if (state == sYellow && iGreen < 100 && mill - past >= interval){
    stand(sYellow);
  }
  else if (state == sYellow && iGreen == 100 && mill - past >= interval){
    stand(sGreen);
  }
  if (state == sGreen && iRed > 15 && mill - past >= interval) {
    stand(sGreen);
  }
  else if (state == sGreen && iRed == 15 && mill - past >= interval){
    stand(sCyan);
  }
  if (state == sCyan && iBlue < 100 && mill - past >= interval) {
    stand(sCyan);
  }
  else if (state == sCyan && iBlue == 100 && mill - past >= interval) {
    stand(sBlue);
  }
  if (state == sBlue   && iGreen > 15 && mill - past >= interval) {
    stand(sBlue);
  }
  else if (state == sBlue   && iGreen == 15 && mill - past >= interval){
    stand(sViolet);
  }
  if (state == sViolet && iRed < 100 && mill - past >= interval) {
    stand(sViolet);
  }
  else if (state == sViolet && iRed == 100 && mill - past >= interval){
    stand(sWhite);
  }
  if (state == sWhite  && iGreen < 100 && mill - past >= interval) {
    stand(sWhite);
  }
  else if (state == sWhite  && iGreen == 100 && mill - past >= interval){
    stand(sLoop);
  }
  if (state == sLoop  && iBlue > 15 && mill - past >= interval) {
    stand(sLoop);
  }
  else if (state == sLoop  && iBlue == 15 && mill - past >= interval){
    stand(sRed);
  }
}

//-----------------------------

//----main()------------------------

void setup() {

pinMode(PWMPinRed, OUTPUT);
pinMode(PWMPinGreen, OUTPUT);
pinMode(PWMPinBlue, OUTPUT);

iRed = iGreen = iBlue = 15;
stand(sInit);/*запустить цепочку начиная с красного*/
}


void loop() {

  mill = millis();
  unitRun();
}

Уважаемые специалисты - кому не лень такое читать, ткните, пожалуйста, носом в косяки.
 
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/*возьмем этот код */
if (state == sRed && iRed < 100 && mill - past >= interval) {
  stand(sRed);
}
else if (state == sRed && iRed == 100 && mill - past >= interval) {
  stand(sYellow);
}
/*немного подумаем и сделаем так*/
if (state == sRed && && mill - past >= interval) {
  if ( iRed < 100) stand(sRed);
  else stand(sYellow);
}
/*ну это так мелочи*/

А если немного поглубже копнуть, то лучше копаться здесь.http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov

Tollmuch
Offline
Зарегистрирован: 20.02.2018

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