снова про "без delay"

jfd
Offline
Зарегистрирован: 28.11.2014

Здравствуйте. Я все понимаю - тема жеванная пережеванная. Но поиском по сайту и гуглу на нашел решение.

Как моргать без делай понятно. Функция blink1sec () работает нормально. Проблема возникает когда надо выполнить функцию blink500mills () - функция выполняется только пока нажата кнопка, не смотря на содержащийся цикл со счетчиком. С одной стороны логично - кнопку отпустили и состояние переменной изменлось и выполнение вернулось функции blink1sec (). Но тогда почему выолняется blinkDelay () при разовом нажатии кнопки и почему она не прекращает работу в момент прохождения через for (почему она работает в действии которое гоняет цикл for понятно).

Собственно основной вопрос как сделать так чтобы blink500mills () выполнился заданное количество раз даже при отпускании кнопки?

Заранее спасибо

/* Blink without Delay
 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 */

const int ledPin =  12;      // номер выхода, подключенного к светодиоду
// Variables will change:
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода
long previousMillis = 0;        // храним время последнего переключения светодиода
const int buttonPin = 7;  //из скетча с кнопкой
int buttonState = 0;    //из скетча с кнопкой
long interval = 3000;           // интервал между включение/выключением светодиода (1 секунда)


void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);   
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);     
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);  
  Serial.begin(9600); 
}

void blink1sec ()
{
// здесь будет код, который будет работать постоянно
// и который не должен останавливаться на время между переключениями свето
unsigned long currentMillis = millis();

//проверяем не прошел ли нужный интервал, если прошел то
if(currentMillis - previousMillis > 1000) {
  // сохраняем время последнего переключения
  previousMillis = currentMillis; 

  // если светодиод не горит, то зажигаем, и наоборот
  if (ledState == LOW)
    
    ledState = HIGH;
    
  else
    
    ledState = LOW;

  // устанавливаем состояния выхода, чтобы включить или выключить светодиод
  digitalWrite(ledPin, ledState); 

}
}
void blink500mills ()
{
// здесь будет код, который будет работать постоянно
// и который не должен останавливаться на время между переключениями свето
unsigned long currentMillis = millis();

//проверяем не прошел ли нужный интервал, если прошел то
for (int counter = 0; counter <=20; counter++)
  {
    if(currentMillis - previousMillis > 100) 
        {
        // сохраняем время последнего переключения
        previousMillis = currentMillis; 
      
        // если светодиод не горит, то зажигаем, и наоборот
        if (ledState == LOW)
          ledState = HIGH;
        else
          ledState = LOW;
        // устанавливаем состояния выхода, чтобы включить или выключить светодиод
        digitalWrite(ledPin, ledState); 
        }   
   }
 }

void blinkDelay ()
{
  for (int counter = 0; counter <=20; counter++)
   {
   digitalWrite (ledPin, HIGH);
   delay (500);
   digitalWrite (ledPin, LOW);
   delay (500);
   }
}  
void loop()
{
  buttonState = digitalRead(buttonPin); // считываем значения с входа кнопки
  Serial.println (buttonState);
  // проверяем нажата ли кнопка
  // если нажата, то buttonState будет HIGH:
  if (buttonState == LOW) {   
    // выпоняет текущую программу
    blink1sec ();  
  }
  else {
    // выполняем аварийную программу
   
   blink500mills ();
   //blinkDelay();
  }
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Сравните две функции, они отличаются принципиально, во второй используется цикл, который сделан неправильно. Потому что как только current достигнет previous, то все кончится, сравнение их всегда будет возвращать true.
И вообще, цикл там не правильный. В цикле проверяется, прошло ли 100 мс от начала цикла. И почему проверка производится только 20 раз? Вы считаете, что один цикл длится 100 мс? Вы ошибаетесь.
Чтобы не зависеть от кнопки, проверьте функции без проверки нажатия кнопки. Раздельно

nikolaki
nikolaki аватар
Offline
Зарегистрирован: 14.02.2013
void setup() {                
pinMode(13, OUTPUT);     
    
}
void loop() {
int x = millis()%1000;
digitalWrite(13, !(x-x%500));

}

 

Параллельные условия для ног

афтар  dimax .Красиво, понравилось . Где-то и maksim использовал подобную красоту. Спасибо ребята .Жжете.

Бесстындо стырил, разобрался   и пользуюсь .

 

Мож не в тему? Ну сорри  тоды...

 

X-Dron
Offline
Зарегистрирован: 24.01.2015

Можно и еще проще

void setup() {               
pinMode(13, OUTPUT);    
     
}
void loop() {
	digitalWrite(13, millis()%1000 < 500);
}
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

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

vov4ik
Offline
Зарегистрирован: 10.09.2013

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

 int a , b, c, d, num;  num = 5836; // далее дробление 

  if (num > 999) {a = (num - (num % 1000)) / 1000;
    num = num % 1000;} else { a = 0;}  
  if (num > 99) { b = (num - (num % 100)) / 100;
    num = num % 100;} else {b = 0;}  
  if (num > 9) {c = (num - (num % 10)) / 10;
    num = num % 10;} else {c = 0;}  
  d = num;

в итоге a = 5 , b = 8 , c = 3 , d = 6 , так дробится четырёхзначное число.