millis() с паузой

ecore
Offline
Зарегистрирован: 22.05.2022

Коллеги, подскажите, не могу понять почему не работает. Нужно, чтобы светодиод поморгал 10 раз с частотой 100 мс, потом пауза 1 секунда и опять моргушки и так далее до бесконечности. Сейчас моргает 10 раз, а потом раз в секунду. Не могу понять почему он переходит на это режим. С Delay все просто, а вот с millis() разобраться не могу.

int ledPin = 13;                      // номер пина со светодиодом
int ledState = LOW;                   // состояние светодиода
int k = 0;                            // для счетчика
// последний момент времени, когда состояние светодиода изменялось
unsigned long previousMillis = 0;

long Time = 100;                   // длительность свечения светодиода (в миллисекундах)
long pause = 1000;
bool state = 0;                       //
void setup() {
  pinMode(ledPin, OUTPUT);         // устанавливаем цифровой пин со светодиодом как ВЫХОД
}

void loop() {
  // выясняем не настал ли момент сменить состояние светодиода
  unsigned long currentMillis = millis();   // текущее время в миллисекундах

  // если светодиод включен и светится больше чем надо
  if ((ledState == HIGH) && (currentMillis - previousMillis >= Time))
  {
    ledState = LOW;                   // выключаем
    previousMillis = currentMillis;   // запоминаем момент времени
    digitalWrite(ledPin, ledState);   // реализуем новое состояние
    k++;
    if (k > 9 ) state = 1;    // если больше переводим в другое состояние
  }
  else if ((ledState == LOW) && (currentMillis - previousMillis >= Time) && !state)    //здесь проверяем 3 пунктом это состояние
  {
    ledState = HIGH;                   // включаем
    previousMillis = currentMillis ;   // запоминаем момент времени
    digitalWrite(ledPin, ledState);    // реализуем новое состояние

  }
  else if ((ledState == LOW) && (currentMillis - previousMillis >= pause) && state == 1)
  {
    state = 0;
  }
}

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Даже нет желания разбирать эти невнятные условия.
Кто вас учит так писать ?
Сделай через switch, сразу понятно станет , где косяк.

ecore
Offline
Зарегистрирован: 22.05.2022

Спасибо конечно за совет, но использование switch case или if это скорее религиозный вопрос. Люди по разному воспринимают. Лично мне switch не нравится, как и многим. Но я попробую воспользоваться вашим советом. 

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Заводите статическую переменную-счетчик

static byte n = 0;

Через каждые 100 мс проверяете значение n - если оно меньше или равно 19, включаете/выключаете светодиод, если больше 19 - выключаете светодиод. Потом увеличиваете n на единицу. Если n >= 30 обнуляете его.

if (++n >= 30){n = 0;}

Таким образом первые 20 циклов светодиод будет включаться и выключаться (включится 10 раз и выключится 10 раз), следующие 10 циклов светодиод светиться не будет. Потом все повторяется и так до бесконечности. 

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

ecore пишет:

использование switch case или if это скорее религиозный вопрос. Люди по разному воспринимают. Лично мне switch не нравится, как и многим. 

Это глупость. Тут вопрос не личных предпочтений, а целесообразности.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ecore пишет:

Спасибо конечно за совет, но использование switch case или if это скорее религиозный вопрос. Люди по разному воспринимают. Лично мне switch не нравится, как и многим. Но я попробую воспользоваться вашим советом. 

Это ни разу не религиозный вопрос.
Это вопрос читаемости кода.

Если будет написано примерно так:

int mode=0;

switch (mode){
case 0:
if(проверка времени){
что то делаем;
инкрементируем переменную;

}
if(переменная >нужного)mode=1;
break;
case 1:
Делаем что то другое;
Если все сделали mode=2;
break;
case 2:
Делаем что то третье;
если надо mode=0;
break;
}

Согласись, это для понимания намного нагляднее.

ecore
Offline
Зарегистрирован: 22.05.2022

Коллеги, спасибо большое за советы, но хочется понять, что именно с кодом не так. Он же очень простой и короткий, если не хочется разбираться, то я вас понимаю. Может кто найдется, кто поможет. Есть подозрение, что проблема именно в millis(), а не в условиях.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ecore пишет:

Коллеги, спасибо большое за советы, но хочется понять, что именно с кодом не так. Он же очень простой и короткий, если не хочется разбираться, то я вас понимаю. Может кто найдется, кто поможет. Есть подозрение, что проблема именно в millis(), а не в условиях.

Проблема именно в условиях.
Конкрентее- некорректный переход от одного условия к другому.
Напиши то же самое через switch и ты ее увидишь

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

ecore пишет:

Коллеги, спасибо большое за советы, но хочется понять, что именно с кодом не так. Он же очень простой и короткий, если не хочется разбираться, то я вас понимаю. Может кто найдется, кто поможет. Есть подозрение, что проблема именно в millis(), а не в условиях.

Проблема в коде, точнее - в подходе. Не нужно усложнять. Там простейший алгоритм.

А millis() проблем никогда и никому не доставляет, по сути это просто счетчик милисекунд с момента старта МК

Kakmyc
Offline
Зарегистрирован: 15.01.2018

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

uint32_t pause100ms=0;
uint32_t pause1sec=0;
boolean blink=0;
int count=0;
boolean ledState=0;
static int ledPin=13;

enum MODE{LIGHT_ON,LIGHT_OFF,PAUSE};
MODE mode=LIGHT_ON;
void setup(){
    pinMode(ledPin,OUTPUT);
}

void loop(){
    switch(mode){

        case LIGHT_ON:
        if(millis()-pause100ms>=100){
            ledState=1;
            mode=LIGHT_OFF;
            pause100ms=millis();
        }
        break;

        case LIGHT_OFF:
        if(millis()-pause100ms>=100){
            ledState=0;
            pause100ms=millis();
            mode=LIGHT_ON;
            count++;}
            if(count==10){
                mode=PAUSE;
                pause1sec=millis();
        }
        break;

        case PAUSE:
        if(millis()-pause1sec>=1000){
                pause100ms=millis();
                mode=LIGHT_ON;
            }
        break;
    }
    digitalWrite(ledPin,ledState);
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ecore пишет:

Коллеги, подскажите, не могу понять почему не работает.

лови, мы люди не гордые )))
 


int ledPin = 13;                      // номер пина со светодиодом
int ledState = LOW;                   // состояние светодиода
int k = 0;                            // для счетчика
// последний момент времени, когда состояние светодиода изменялось
unsigned long previousMillis = 0;

long Time = 100;                   // длительность свечения светодиода (в миллисекундах)
long pause = 1000;
bool state = 0;                       //
void setup() {
  pinMode(ledPin, OUTPUT);         // устанавливаем цифровой пин со светодиодом как ВЫХОД
}

void loop() {
  // выясняем не настал ли момент сменить состояние светодиода
  unsigned long currentMillis = millis();   // текущее время в миллисекундах

  // если светодиод включен и светится больше чем надо
  if ((ledState == HIGH) && (currentMillis - previousMillis >= Time))
  {
    ledState = LOW;                   // выключаем
    previousMillis = currentMillis;   // запоминаем момент времени
    digitalWrite(ledPin, ledState);   // реализуем новое состояние
    k++;
    if (k > 9 ) {state = 1; k=0;}   // если больше переводим в другое состояние
  }
  else if ((ledState == LOW) && (currentMillis - previousMillis >= Time) && !state)    //здесь проверяем 3 пунктом это состояние
  {
    ledState = HIGH;                   // включаем
    previousMillis = currentMillis ;   // запоминаем момент времени
    digitalWrite(ledPin, ledState);    // реализуем новое состояние

  }
  
  else if ((ledState == LOW) && (currentMillis - previousMillis >= pause) && state == 1)
  {
    state = 0;
    }
}

 

Pyotr
Offline
Зарегистрирован: 12.03.2014

А можно и чуть короче

if(millis - previousMillis >= interval) {
    previousMillis = millis;       
    ledState = count % 2 && count < 20;   
    digitalWrite(ledPin, ledState);
    if(++count >=30) count = 0;
  }

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Pyotr пишет:

А можно и чуть короче

if(millis - previousMillis >= interval) {
    previousMillis = millis;       
    ledState = count % 2 && count < 20;   
    digitalWrite(ledPin, ledState);
    if(++count >=30) count = 0;
  }

 

 

Это для того что бы он ещё больше запутался ?

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

И то каждый раз придётся вникать в то, что же делает данный кусок кода.

Зачем ?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Kakmyc пишет:

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

И то каждый раз придётся вникать в то, что же делает данный кусок кода.

Глупости. Простейший вариант. А чтобы не разбираться каждый раз, достаточно пару строк комментариев записать

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

Да это все millis() !!! Я бы даже сказал - заговор от millis() !!! )

b707
Offline
Зарегистрирован: 26.05.2017

ua6em пишет:

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

да он давно на вас забил, обиделся, наверно. что не поддержали его обвинения против коварной миллис()

ecore
Offline
Зарегистрирован: 22.05.2022

Мне некогда обижаться, просто был занят. 

ecore
Offline
Зарегистрирован: 22.05.2022

ua6em пишет:

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

Да именно это я и просил. Спасибо.

ecore
Offline
Зарегистрирован: 22.05.2022

ua6em пишет:

ecore пишет:

Коллеги, подскажите, не могу понять почему не работает.

лови, мы люди не гордые )))
 


int ledPin = 13;                      // номер пина со светодиодом
int ledState = LOW;                   // состояние светодиода
int k = 0;                            // для счетчика
// последний момент времени, когда состояние светодиода изменялось
unsigned long previousMillis = 0;

long Time = 100;                   // длительность свечения светодиода (в миллисекундах)
long pause = 1000;
bool state = 0;                       //
void setup() {
  pinMode(ledPin, OUTPUT);         // устанавливаем цифровой пин со светодиодом как ВЫХОД
}

void loop() {
  // выясняем не настал ли момент сменить состояние светодиода
  unsigned long currentMillis = millis();   // текущее время в миллисекундах

  // если светодиод включен и светится больше чем надо
  if ((ledState == HIGH) && (currentMillis - previousMillis >= Time))
  {
    ledState = LOW;                   // выключаем
    previousMillis = currentMillis;   // запоминаем момент времени
    digitalWrite(ledPin, ledState);   // реализуем новое состояние
    k++;
    if (k > 9 ) {state = 1; k=0;}   // если больше переводим в другое состояние
  }
  else if ((ledState == LOW) && (currentMillis - previousMillis >= Time) && !state)    //здесь проверяем 3 пунктом это состояние
  {
    ledState = HIGH;                   // включаем
    previousMillis = currentMillis ;   // запоминаем момент времени
    digitalWrite(ledPin, ledState);    // реализуем новое состояние

  }
  
  else if ((ledState == LOW) && (currentMillis - previousMillis >= pause) && state == 1)
  {
    state = 0;
    }
}

 

Спасибо большое.

ecore
Offline
Зарегистрирован: 22.05.2022

Kakmyc пишет:

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

uint32_t pause100ms=0;
uint32_t pause1sec=0;
boolean blink=0;
int count=0;
boolean ledState=0;
static int ledPin=13;

enum MODE{LIGHT_ON,LIGHT_OFF,PAUSE};
MODE mode=LIGHT_ON;
void setup(){
    pinMode(ledPin,OUTPUT);
}

void loop(){
    switch(mode){

        case LIGHT_ON:
        if(millis()-pause100ms>=100){
            ledState=1;
            mode=LIGHT_OFF;
            pause100ms=millis();
        }
        break;

        case LIGHT_OFF:
        if(millis()-pause100ms>=100){
            ledState=0;
            pause100ms=millis();
            mode=LIGHT_ON;
            count++;}
            if(count==10){
                mode=PAUSE;
                pause1sec=millis();
        }
        break;

        case PAUSE:
        if(millis()-pause1sec>=1000){
                pause100ms=millis();
                mode=LIGHT_ON;
            }
        break;
    }
    digitalWrite(ledPin,ledState);
}

 

Возможно Вам так проще, но к сожалению этот код не работает. 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ecore пишет:

Kakmyc пишет:

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

uint32_t pause100ms=0;
uint32_t pause1sec=0;
boolean blink=0;
int count=0;
boolean ledState=0;
static int ledPin=13;

enum MODE{LIGHT_ON,LIGHT_OFF,PAUSE};
MODE mode=LIGHT_ON;
void setup(){
    pinMode(ledPin,OUTPUT);
}

void loop(){
    switch(mode){

        case LIGHT_ON:
        if(millis()-pause100ms>=100){
            ledState=1;
            mode=LIGHT_OFF;
            pause100ms=millis();
        }
        break;

        case LIGHT_OFF:
        if(millis()-pause100ms>=100){
            ledState=0;
            pause100ms=millis();
            mode=LIGHT_ON;
            count++;}
            if(count==10){
                mode=PAUSE;
                pause1sec=millis();
        }
        break;

        case PAUSE:
        if(millis()-pause1sec>=1000){
                pause100ms=millis();
                mode=LIGHT_ON;
            }
        break;
    }
    digitalWrite(ledPin,ledState);
}

 

Возможно Вам так проще, но к сожалению этот код не работает. 

Так он и не работает точно из за того же, почему не работает ваш код.
Но тут это очевидно, а у вас нет.

ecore
Offline
Зарегистрирован: 22.05.2022

Kakmyc][quote=ecore]</p> <p>[quote=Kakmyc пишет:

 Так он и не работает точно из за того же, почему не работает ваш код. Но тут это очевидно, а у вас нет.

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

Спасибо всем за указание ошибки. Думаю тему можно закрыть.