Отказ от delay()

ustas
Offline
Зарегистрирован: 12.03.2012

Все мы знаем чудесный пример "моргаем светодиодом без delay()" - приведу его еще разок:


const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

Естественно, тут все чудесно работает.

А вот как быть, когда delay() требуется внутри функции?

Пример:

void setup() {
  ...
}

void loop() {
  ...
  func(...);
  ...
}

float func(...) {
  ...
  delay(...);
  ...
}

Когда у нас требуется задержка в loop - тут все понятно, а как в этом случае поступать? В функцию передали активность, но вот функция должна подождать (например, как это происходит в случае работы с датчиком DS18B20).

Как организовать задержку в этом случае?

maksim
Offline
Зарегистрирован: 12.02.2012

Да точно также.

const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  Blink();
}

void Blink(){
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

 

ustas
Offline
Зарегистрирован: 12.03.2012

да, так понятно, но при этом пока "не вернемся" из функции Blink - ничего не происходит.

реальный пример:

есть микроконтроллер, к которому подключен ИК-приемник (обрабатываем ИК-команды), датчик DS18B20 (меряем температуру), RF-трансивер (беспроводное управление и "съем данных" с "датчиков", ну и пара управляемых цепей.

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

 

Как обойти?

maksim
Offline
Зарегистрирован: 12.02.2012

 

ustas пишет:

да, так понятно, но при этом пока "не вернемся" из функции Blink - ничего не происходит.

Это почему? Все происходит, мы "пролитаем" функцию Blink насвозь без задержек.

ustas пишет:

Как обойти?

Да, очень просто, когда заходите в функцию измерения температуры проверяете флаг, если не взведен, то отправляете команду конвертации температуры, взводите флаг и так же как в Blinkе ждете, сбрасываете этот флаг после того как истекло время.

 

maksim
Offline
Зарегистрирован: 12.02.2012

Покажите свою функцию измерения температуры.

ustas
Offline
Зарегистрирован: 12.03.2012

Ничего экзотического:

float Get_18B20_Data(){
  byte DSdata[2];
  ds.reset(); 
  ds.write(0xCC);
  ds.write(0x44);
  delay(800);
  ds.reset();
  ds.write(0xCC);
  ds.write(0xBE);
  DSdata[0] = ds.read(); 
  DSdata[1] = ds.read();
  int Temp = (DSdata[1] << 8) + DSdata[0];
  return (float) Temp / 16;
}


 

maksim
Offline
Зарегистрирован: 12.02.2012

Объявляете глобально переменные 

boolean flag = 0;
unsigned long new_time = 0;
byte DSdata[2];

и делаете так

float Get_18B20_Data(){
  if(!flag){
    ds.reset(); 
    ds.write(0xCC);
    ds.write(0x44);
    flag = 1;
    new_time = millis() + 800;
  }
  else if(millis() > new_time){
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    DSdata[0] = ds.read(); 
    DSdata[1] = ds.read();
    flag = 0;
  }
  int Temp = (DSdata[1] << 8) + DSdata[0];
  return (float) Temp / 16;
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

И естественно первые 800 мс функция будет возвращать 0.

ustas
Offline
Зарегистрирован: 12.03.2012

да, так будет работать, если в loop просто будем дергать эту функцию и ждать, когда она отдаст ответ.

но в реальной жизни, так не получится (в моем случае) - эта функция вызывается, когда от "главного" модуля через RF-трансивер пришел соотвествтвующий запрос. Соответственно, первый вызов этой функции ничего не даст - придется  продолжать опрашивать ее до появления ответа (правда, тут параллельно можно успевать и все прочие дела делать).

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

Что скажете про такой подход?

maksim
Offline
Зарегистрирован: 12.02.2012

Можно и так, можно как угодно, решений миллион. Температура параметр инерционный, поэтому можно и раз в минуту обновлять. Вы можете объявить глобально int Temp, функцию сделать void и увеличить в 07 строке время new_time = millis() + 60000; и будет вам обновление раз в минуту.

axill
Offline
Зарегистрирован: 05.09.2011

В чем необходимость отказываться от delay? Это не может быть самоцелью. В примере с blink просто продемонстрировано как работать с прерываниями, не более. Чтобы моргать светодиодом и ничего более при этом не делать прерывания не нужны.

maksim
Offline
Зарегистрирован: 12.02.2012

1. Прочитайте внимально сообщение #2 и поймете зачем ustas хочет избавиться от delay.
2. Причем здесь прерывания?

axill
Offline
Зарегистрирован: 05.09.2011

maksim пишет:

1. Прочитайте внимально сообщение #2 и поймете зачем ustas хочет избавиться от delay.
2. Причем здесь прерывания?

вы правы - не внимательно прочитал. Когда разбирался с таймерами там тоже был пример blink без delay

maksim
Offline
Зарегистрирован: 12.02.2012

В данном случае скорее всего прерывание по таймеру не прокатит, так как OneWire использует задержки, а как известно задержки в прерывании ведут себя некорректно. Если только в прерывании взводить флаг, который будет проверяться в основном цикле.

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

Коллеги!

Чтобы навсегда забыть о millis(),  lastMillis, previousMillis и расстановке флагов

посмотрите простенькую бибпиотеку:

http://arduino.cc/playground/Code/SimpleTimer

Сказка!

В сетупе 
  timer.setInterval(15000, RepeatTask);
  timer.setTimeout(10000, OnceOnlyTask);
  timer.setInterval(1000, DigitalClockDisplay);
  timer.setTimer(1200, TenTimesTask, 10);

В лупе только     timer.run();

Сама с миллисами работает,

можно выполнять единожды, можно энное количество раз, можно периодически...

Таймеры можно разрешать, запрещать, удалять, рестартовать как угодно(но обычно это не надо)

Очень удобно работает setTimeout - вставляется вместо delay()

 

CheBuraw
Offline
Зарегистрирован: 10.02.2015

Подскажите и мне пожалуйста как мне избавиться от delay! Уже всю голову себе сломал. Идея в том чтобы включать фотоаппарат, делать фото и выключать фотик. В данный момент все работает нормально, но delay не позволяет нормально вывыдить информацию на LCD экран во время выполнения функции фотографирования.

void foto(){ // Функция фотографирования
// Включаем фотик
digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
delay(500);// ждём пол секунды
digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
delay(5000);// ждём пару секунд

// Фотографируем первый раз
digitalWrite(fksPin, HIGH); // подаём напряжение на фокус
delay(1000);// ждём секунду
digitalWrite(shtPin, HIGH); // Подаём напряжение на спуск
delay(500);// ждём полсекунды
digitalWrite(fksPin, LOW); // отключаем напряжение на фокус
digitalWrite(shtPin, LOW); // отключаем напряжение на спуск
delay(5000);// ждём секунду

// Выключаем фотик
digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
delay(1000);// ждём пол секунды
digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
}

Под спойлером моя (неработающая) версия без delay.

void foto(){ // Функция фотографирования
long fotoTime = millis();    //предыдущее показание миллисекунд для обновления
int nmrDST = 0;    //номер действия при фотографировании

// Включаем фотик
  if(millis() - fotoTime > 0 && nmrDST == 0) {
   digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение 
    nmrDST = 1; //разрешение на выполнение следующего действия
  }
//если прошла секунда и есть добро на следующее действие, то действуем
  if(millis() - fotoTime > 1000 && nmrDST == 1) { 
   digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
    nmrDST = 2;
  }

// Фотографируем первый раз
  if(millis() - fotoTime > 6000 && nmrDST == 2) {
   digitalWrite(fksPin, HIGH); // подаём напряжение на фокус
    nmrDST = 3;
  }
    if(millis() - fotoTime > 7000 && nmrDST == 3) {
   digitalWrite(shtPin, HIGH); // Подаём напряжение на спуск
    nmrDST = 4;
  }
      if(millis() - fotoTime > 8000 && nmrDST == 4) {
   digitalWrite(fksPin, LOW); // отключаем напряжение на фокус
   digitalWrite(shtPin, LOW); // отключаем напряжение на спуск
    nmrDST = 5;
  }

// Выключаем фотик
  if(millis() - fotoTime > 13000 && nmrDST == 5) {
   digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение 
    nmrDST = 6;
  }
  if(millis() - fotoTime > 14000 && nmrDST == 6) {
   digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
    nmrDST = 0;
  }

}

Буду Вам очень признателен, если подскажете как решить мою проблему.

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

Переменные nmrDST и fotoTime должны быть глобальные. fotoTime присваивайте время не при входе в функцию а при исполнении очередного действия, после присвоения nmrDST=..  (обычно переменную такого типа как nmrDST называют "состояние", а сам подход  - машина состояний)

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

А вобще, Вы движитесь верным путем. Так тогда уж идите до конца: обявляете const массив ArrTime для хранения временных интервалов, причем в данном случае в сотнях мимлсекунд, т.е. вместо 14000 храним 140, для экономии. В начале функции проверяем типа  if(millis()-fotoTime < ArrTime[nmrDST]*100) return; Соответственно в проверках времени в остальных местах нет нужды и вместо кучи if пишем один switch. Для полного отпада - значения nmrDST обявляем в enum в виде констант с осмымленными названиями. И на последок - оптимизируем switch как получатся будет по ситуации.

maksim
Offline
Зарегистрирован: 12.02.2012
byte state = 0;

void setup() 
{                
  pinMode(13, OUTPUT);    
  state = 1; // 1 запускает foto()
}

void loop() 
{
  foto();
}

void foto() // Функция фотографирования
{
  static uint32_t premillis = 0, interval = 0;
  if(!state && millis()-premillis < interval) return;
  premillis = millis();
  //static byte state = 0;
  
  switch(state)
  {
  case 1:
    // Включаем фотик
    digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
    interval = 500;// ждём пол секунды
    break;

  case 2:
    digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
    interval = 5000;// ждём пару секунд
    break;

  case 3:
    // Фотографируем первый раз
    digitalWrite(fksPin, HIGH); // подаём напряжение на фокус
    interval = 1000;// ждём секунду
    break;

  case 4:
    digitalWrite(shtPin, HIGH); // Подаём напряжение на спуск
    interval = 500;// ждём полсекунды
    break;

  case 5:
    digitalWrite(fksPin, LOW); // отключаем напряжение на фокус
    digitalWrite(shtPin, LOW); // отключаем напряжение на спуск
    interval = 5000;// ждём секунду
    break;

  case 6:
    // Выключаем фотик
    digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
    interval = 1000;// ждём пол секунды
    break;

  case 7:
    digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
    interval = 0;
    break;
  }
  
  state++;
  if(!interval) state = 0;
}

 

CheBuraw
Offline
Зарегистрирован: 10.02.2015

Ого! Оперативно ответили :)

maksim, опробовал Ваш вариант. Не работает :(. При вызове функции без интервалов отрабатывают первые три case, При следующем запуске отрабатывают остальные 4-7 case. Последующие вызовы функции вообще тишина. :(
 

void foto() // Функция фотографирования
{
  static uint32_t premillis = 0, interval = 0;
  if(!state && millis()-premillis < interval) return;
  premillis = millis();
  //static byte state = 0;
  switch(state)
  {
  case 1:
    // Включаем фотик
    digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
   Serial.println("case 1");
    interval = 500;// ждём пол секунды
    break;

  case 2:
    digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
   Serial.println("case 2");
    interval = 5000;// ждём пару секунд
    break;

  case 3:
    // Фотографируем первый раз
    digitalWrite(fksPin, HIGH); // подаём напряжение на фокус
   Serial.println("case 3");
    interval = 1000;// ждём секунду
    break;

  case 4:
    digitalWrite(shtPin, HIGH); // Подаём напряжение на спуск
   Serial.println("case 4");
    interval = 500;// ждём полсекунды
    break;

  case 5:
    digitalWrite(fksPin, LOW); // отключаем напряжение на фокус
    digitalWrite(shtPin, LOW); // отключаем напряжение на спуск
   Serial.println("case 5");
    interval = 5000;// ждём секунду
    break;

  case 6:
    // Выключаем фотик
    digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
   Serial.println("case 6");
    interval = 1000;// ждём пол секунды
    break;

  case 7:
    digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
   Serial.println("case 7");
    interval = 0;
    break;
  }
  state++;
  if(!interval) state = 0;
}

Logik, Ваше предложение не проверял, т.к. пока продумываю код для написания, согласно Ваших рекомендаций.

maksim
Offline
Зарегистрирован: 12.02.2012

Замените && на ||

      if(!state || millis()-premillis < interval) return;
CheBuraw
Offline
Зарегистрирован: 10.02.2015

не, все равно получается что при первом вызове отрабатывается case 1 и case 2 с задержкой похожей на секунду. А вот дальше каждый case срабатывает только при очередном вызове функции. :(

maksim
Offline
Зарегистрирован: 12.02.2012

Естественно, все от того, что вы не понимаете, что такое неблокирующая функция и как ей пользоваться. С чего вы взяли, что нужно вызывать функцию foto()? Где должна быть функция и как ею пользоваться показано в моем примере, если не понятно, то обьясняю: функция foto() должна находиться (вызываться) в функции loop() и нигде больше, что бы запустить последовательность фотографирования необходимо выполнить: state = 1;, в моем примере это делается в функции setup().

Может так будет понятнее:

byte state = 0;

void setup() 
{                   
  
}

void loop() 
{
  ...
  if(digitalRead(BUTTON)) foto();
  ...
  ...
  fotorun();
  ...
}



void foto() // запуск фотографирования
{
  state = 1; // 1 запускает foto()
}

void fotorun() // Функция фотографирования
{
  static uint32_t premillis = 0, interval = 0;
  if(!state || millis()-premillis < interval) return;
  premillis = millis();
  //static byte state = 0;
  
  switch(state)
  {
  case 1:
    // Включаем фотик
    digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
    interval = 500;// ждём пол секунды
    break;

  case 2:
    digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
    interval = 5000;// ждём пару секунд
    break;

  case 3:
    // Фотографируем первый раз
    digitalWrite(fksPin, HIGH); // подаём напряжение на фокус
    interval = 1000;// ждём секунду
    break;

  case 4:
    digitalWrite(shtPin, HIGH); // Подаём напряжение на спуск
    interval = 500;// ждём полсекунды
    break;

  case 5:
    digitalWrite(fksPin, LOW); // отключаем напряжение на фокус
    digitalWrite(shtPin, LOW); // отключаем напряжение на спуск
    interval = 5000;// ждём секунду
    break;

  case 6:
    // Выключаем фотик
    digitalWrite(vklPin, HIGH);  // Подаём напряжение на включение
    interval = 1000;// ждём пол секунды
    break;

  case 7:
    digitalWrite(vklPin, LOW);  // отключаем напряжение на включение
    interval = 0;
    break;
  }
  
  state++;
  if(!interval) state = 0;
}

В этом случае fotorun() вызывается в loop(), а foto() вызывайте там где вызываете.

CheBuraw
Offline
Зарегистрирован: 10.02.2015

maksim, не ругайтесь. Вы все правильно сказали - не понимаю я что такое неблокирующая функция. Честно говоря, я до этого и вообще не знал про такие :). Сделал все как Вы порекомендовали... все чётко работает. Спасибо!

Пельмень
Offline
Зарегистрирован: 23.03.2015

Здравствуйте!Писал в соседней ветке...В ардуино новичок,поэтому делаю много ошибок...Стоит задача работа светофора,запускаемая удержанием кнопки 5сек.,с начала работы программы 2сек.Уважаемый maksim направил на эту ветку форума,за что ему отдельная благодарность...Код я написал,но почему-то не работает.Буду рад любой помощи и соответственно любым комментариям.Заранее спасибо

int pedYellow = 12; //желтый
int pedRed = 13;   //Красный
int pedGreen = 8;  //Зеленый
int button = 2;    //Контакт кнопки
 
int crossTime = 5000; //Время ожидания
unsigned long changeTime; //Время с начала работы программы
 
void setup() {
  // Контакты на выход
  pinMode(pedYellow, OUTPUT);  // Светодиод желтый
  pinMode(pedRed, OUTPUT);   //светодиод красный
  pinMode(pedGreen, OUTPUT);
  //Контакт на вход (кнопка)
  pinMode(button, INPUT);}
//Кнопка
 
void loop() {
  //Нажать кнопку 
  int state = digitalRead(button); //Получаем статус кнопки
  delay(5000);
  int state2 = digitalRead(button);
  //Если кнопка нажата и время с начала работы программы минус changeTime больше 2 сек, то
  if (state == state2) {
    if (state == HIGH && (millis() - changeTime) > 2000) {
      //1. Действие
      digitalWrite(pedYellow, HIGH); // Включаем желтый
      delay(2000); // Ждем 2 сек
      //2. Действие
      digitalWrite(pedYellow, LOW); // Выключаем желтый
      digitalWrite(pedRed, HIGH);   // Включаем красный
      delay(1000); // Ждем 1 сек
      //3. Действие
      digitalWrite(pedRed, LOW); // Выключаем красный
      digitalWrite(pedGreen, HIGH); // Включаем зеленый
      delay(crossTime); // Ждем 5 сек
      // Мигаем зеленым для пешеходов 5 раз
      for (int x = 0; x < 5; x++) {
        digitalWrite(pedGreen, HIGH);
        delay(250);
        digitalWrite(pedGreen, LOW);
        delay(250);
      }
      
    }changeTime = millis();      //changeTime равно время с начала работы программы
    }
  }
 
 
 
vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Пельмень

У Вас вот эта проверка if (state == HIGH && (millis() - changeTime) > 2000)  никогда не будет истиной

потому что перед этим в коде if (state == state2) - changeTime = millis(); разница в 2 сек.  наступить не может

Зачем Вы добавляете еще 2000 если перед этим делали задержку 5000

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

void loop() 
{
	
	if (digitalRead(button) == HIGH)
	{
		delay(5000);
		if (digitalRead(button) == HIGH)
		{
		//1. Действие
      digitalWrite(pedYellow, HIGH); // Включаем желтый
      delay(2000); // Ждем 2 сек
      //2. Действие
      digitalWrite(pedYellow, LOW); // Выключаем желтый
      digitalWrite(pedRed, HIGH);   // Включаем красный
      delay(1000); // Ждем 1 сек
      //3. Действие
      digitalWrite(pedRed, LOW); // Выключаем красный
      digitalWrite(pedGreen, HIGH); // Включаем зеленый
      delay(crossTime); // Ждем 5 сек
      // Мигаем зеленым для пешеходов 5 раз
      for (int x = 0; x < 5; x++) 
      {
      	digitalWrite(pedGreen, HIGH);
      	delay(250);
      	digitalWrite(pedGreen, LOW);
      	delay(250);
      }
  }

}
}

 

Пельмень
Offline
Зарегистрирован: 23.03.2015

Благдарю за участие!!!

Пельмень
Offline
Зарегистрирован: 23.03.2015

ТЗ изменилось маленько,пока Вы мне открывали глаза,но в любом случае спасибо

Genplane
Offline
Зарегистрирован: 16.04.2014

Добрый день! Пытался несколько раз скопировать эту библиотеку - не получается, Скетч её не видит.  Адрес папки:      

 Program Files(x86)\Arduino\libraries\SimpleTimer\SimpleTimer.h\SimpleTimer.h

 Выдаёт ошибку:

Arduino: 1.6.7 (Windows 10), Плата:"Arduino/Genuino Uno"

 
C:\Users\Asus\Documents\Arduino\Zadergka_s_SimpleTimer\Zadergka_s_SimpleTimer.ino:1:25: fatal error: SimpleTimer.h: No such file or directory
 
 #include <SimpleTimer.h>
 
                         ^
 
compilation terminated.
 
exit status 1
Ошибка компиляции.
 
Что делаю не так?
Спасибо
 

 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

Genplane пишет:

Добрый день! Пытался несколько раз скопировать эту библиотеку - не получается, Скетч её не видит.  Адрес папки:      

 Program Files(x86)\Arduino\libraries\SimpleTimer\SimpleTimer.h\SimpleTimer.h

 Выдаёт ошибку:

Arduino: 1.6.7 (Windows 10), Плата:"Arduino/Genuino Uno"

 
C:\Users\Asus\Documents\Arduino\Zadergka_s_SimpleTimer\Zadergka_s_SimpleTimer.ino:1:25: fatal error: SimpleTimer.h: No such file or directory
 
 #include <SimpleTimer.h>
 
                         ^
 
compilation terminated.
 
exit status 1
Ошибка компиляции.
 
Что делаю не так?
Спасибо
 

 

он же просит положить библиотеку сюда

C:\Users\Asus\Documents\Arduino\libraries

Genplane
Offline
Зарегистрирован: 16.04.2014

Сделал. Не помогло. У меня две папки Arduino:

C:\Users\Asus\Documents\Arduino\libraries

 C:\Program Files(x86)\Arduino\libraries

Может, удалить вторую? Скетч, похоже, к ней обращается.

Спасибо

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

В програм файлес лежит комплект поставки ИДЕ.
Пусть лежит. Не трогайте там ничего.

Все ваши "любимые" библиотеки держите под юзером.
А удалить там можете хоть и все.
Если они вам совсем не нужны.
Тогда блинк точно будет работать!

Genplane
Offline
Зарегистрирован: 16.04.2014

Понял. Спасибо. Юмор заценил. Буду тренироваться дальше

bwn
Offline
Зарегистрирован: 25.08.2014

"SimpleTimer.h" достаньте из папки с аналогичным именем и переложите в папку "SimpleTimer"

Genplane
Offline
Зарегистрирован: 16.04.2014

Спасибо. Проблема была в неправильном расширении. По ссылке сказано скачать и положить в папку. Но нужно ещё и отредактировать в специальном редакторе, чтобы у файла появилось расширение .hи .cpp. Вот на этом и забуксовал. Поэтому нашёл в инете архивированную библиотеку и вставил без проблем в Ардуино. Всё заработало. Всем спасибо.

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

Тест удачности отписки об уведомлениях......

bwn
Offline
Зарегистрирован: 25.08.2014

trembo пишет:

Тест удачности отписки об уведомлениях......

Контрольный выстрел))))

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

Фигвам ! ( индейское жилище)
Мимо!
Отписка работает!
Тема 2012 года была в засушенном состоянии,
я тогда ещё совсем молодой был, тогда и подписался, а тут вдруг пошли сообщения.

Сергей Р
Offline
Зарегистрирован: 19.02.2016

Привет всем знатокам, прошу не пинать, только начинаю.

Помогите с задачкой пожалуйста, условия таковы:

Нажимаю на кнопку включается на 1сек один светодиод, отпускаю кнопку включается на 1сек другой светодиод.

Код ниже, только переключает светодиоды, а нужно вкл. на 1сек.

// задаем константы
const int buttonPin = 2;     // номер входа, подключенный к кнопке
const int ledPin =  13;      // номер выхода светодиода
const int ledPinw =  7;      // номер выхода светодиода синий
// переменные
int buttonState = 0;         // переменная для хранения состояния кнопки
 
void setup() {
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);   
   pinMode(ledPinw, OUTPUT);    
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);   
}
 
void loop(){
  // считываем значения с входа кнопки
  buttonState = digitalRead(buttonPin);
 
  // проверяем нажата ли кнопка
  // если нажата, то buttonState будет HIGH:
  if (buttonState == HIGH) {   
    // включаем светодиод   
    digitalWrite(ledPin, LOW); 
      digitalWrite(ledPinw,!digitalRead(ledPinw));//инвертируем состояние пина 
  }
  else {
    // выключаем светодиод
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPinw, HIGH); 
  }
}

 

dizzel
Offline
Зарегистрирован: 21.03.2016
Добрый день.
Пытаюсь запрограммировать светодиоды WS2812
Эта функция последовательно меняет цвет в каждом пикселе через промежуток времени.
void colorWipe(uint32_t c, uint16_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    if(chkBtn(digitalRead(BTN_PIN))) { break; }
      strip.setPixelColor(i, c);
      strip.show();
      delay (wait);
  }
}
 
Я всю голову сломал как избавится от delay
Пока выполняется этот delay я не могу обработать нажатие кнопки.
Помогите пожалуйста.
Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014
dizzel
Offline
Зарегистрирован: 21.03.2016

Ссылок и я накидать могу. Только вот видел я уже это. Не пойму где ставить условие на срабатывание. До цикла - все диоды обновятся одновременно. После - будут обновляться не последовательно, а группами по 2 по три и т.д. Объясните пжлст как тут поступить.

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

millis(). А еще проще создаешь класс с setup() и loop() методами .

dizzel
Offline
Зарегистрирован: 21.03.2016

Не могли бы вы напримере кода который я привел показать как это сделать?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
void colorWipe_loop(uint32_t c, uint16_t wait) {
  static uint32_t past = 0;
  static uint16_t i = 0;
  if (millis() - past >= wait) {
    past = millis();
    if (chkBtn(digitalRead(BTN_PIN))) break;
    i++;
    if (i >= strip.numPixels()) i = 0;
    strip.setPixelColor(i, c);
    strip.show();
  }
}

void setup() {


}

void loop() {
  colorWipe_loop(5,500);

}

 

RustG
Offline
Зарегистрирован: 25.11.2017

Доброго времени суток!

      Так уж случилось, что я технарь, но не программист. Прошу сразу не пинать и не отправлять по ссылкам. Неделю уже бьюсь над проблемой, пересмотрел кучу страниц текста, кода, объяснений...
Есть скетч управления WS2812 по принципу, что все модули ленты горят своим цветом исходя из места в массиве, но если Цвет задан КРАСНЫЙ, то данные светодиоды должны еще и моргать одновременно... Так вот при реализации с delay они моргают по очереди (циклично). Без delay (с применение millis) никак не получается их заставить моргать даже по очереди, а надо чтоб без delay и моргали все красные одновременно.

 #include "FastLED.h"          // библиотека для работы с лентой

#define Quant 50 // число светодиодов в ленте
#define PIN 6 // назначаем управляющий лентой пин.
struct CRGB leds[Quant];
int PointMap[] = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 1, 4, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 1, 4, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 1};

void setup()
{
  Serial.begin(9600);              // открыть порт для связи

  FastLED.addLeds<WS2812B, PIN, RGB>(leds, Quant);  // настройки для нашей ленты (ленты на WS2811, WS2812, WS2812B)
  FastLED.show();                     // отослать команду
  delay(1000);
  //----------------------------SetAll-------------------------------------//
  for (int i = 0; i < Quant; i++) {
    if (PointMap[i] == 1) {
      setPixel(i, 255, 0, 0); //Красный
    }
    else {
      if (PointMap[i] == 2) {
        setPixel(i, 0, 0, 255); //синий
      }
      else {
        if (PointMap[i] == 3) {
          setPixel(i, 255, 255, 0); //желтый
        }
        else {
          if (PointMap[i] == 4) {
            setPixel(i, 255, 0, 255); //Фиолетовый
          }
          else {
            if (PointMap[i] == 5) {
              setPixel(i, 255, 255, 255); //Белый
            }
            else {
              if (PointMap[i] == 0) {
                setPixel(i, 0, 255, 0);//Зеленый
              }
            }
          }
        }
      }
    }
  }
}
void loop() {
  BlinkRed();
}

//----------------------------setPixel-------------------------------------//
void setPixel(int i, byte red, byte green, byte blue) {
  leds[i].r = red;
  leds[i].g = green;
  leds[i].b = blue;
}
//----------------------------BlinkRed-------------------------------------//
void BlinkRed() {
  for (int i = 0; i < Quant ; i++) {
    if (PointMap[i] == 1) {
      setPixel(i, 0, 0, 0);//Выключен
      FastLED.show();
      delay(200);
      setPixel(i, 255, 0, 0);//Красный
      FastLED.show();
      delay(150);
      //FastLED.show();
    }
  }
}

Направьте, плиз, в нужном направлении. :)

kalapanga
Онлайн
Зарегистрирован: 23.10.2016

То есть, остальные диоды как зажглись один раз своим цветом, так и горят, а которые должны быть красными весело мигают?

Так а в чём отличие от примера Blink without delay? Берёте прямо его. Только там где по прошествии нужного времени состояние одного диода меняется, Вам в цикле по всем пробежаться нужно будет. Я с этой библиотекой не знаком, но скорее всего FastLED.show() можно один раз после установки состояния всех красных сд вызывать.

RustG
Offline
Зарегистрирован: 25.11.2017

Пока именно так.. Позже на разные данные буду навешивать разные типы индикации, и прочее - прочее...

Подобие из Blink without delay не получается, тк (как я понимаю) в ленту надо запустить последовательность битов, а лента чувствительна к временным интервалам и не получается точно выставить таймауты горения и выключения... Может это и не так, но у меня пока ничего не получилось... Пробую-пробую, но пока безрезультатно(

 

 

RustG
Offline
Зарегистрирован: 25.11.2017

В ардафруит библиотеке тоже ничего не выходит...

 

arduino328
Offline
Зарегистрирован: 01.09.2016

RustG пишет:

Направьте, плиз, в нужном направлении.

void BlinkRed() {
  for (int i = 0; i < Quant ; i++) {
    setPixel(i, 0, 0, 0);  // Выключен
  }
  FastLED.show();
  delay(200);

  for (int i = 0; i < Quant ; i++) {
    setPixel(i, 255, 0, 0);  // Красный
  }
  FastLED.show();
  delay(150);
)

 

kalapanga
Онлайн
Зарегистрирован: 23.10.2016

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