как заменить delay

anderlei
Offline
Зарегистрирован: 20.06.2017

Доброе время суток. Делаю свой первый проект на Arduino  где необходимо реализовать плавное включение светодиода, нашёл с примеров вот такое

  for(int brightness=0;brightness<=255;brightness++){
    analogWrite(PIN_alarm_LED, brightness);
    delay(10000); 

Все работает отлично, только delay останавливает остальные действия ардуины, подскажите как поменять delay на Millis. Все примеры с Millis какие находил не смог связать вместе. Спасибо! 

 

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

anderlei пишет:

Все примеры с Millis какие находил не смог связать вместе. Спасибо! 

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

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016
static uint32_t old_time = millis(); //старое время хранится в статической переменной
// то есть оно не будет меняться при каждом входе в loop()
// инициализация выполнится ТОЛЬКО ОДИН РАЗ

uint32_t new_time = millis();
//новое время обновляется ПРИ КАЖДОМ входе в loop()

static int brightness=0; // хряним яркость тоже статически

if (brightness < 255) // пока яркость не достигла максимума   
  if (new_time - old_time > 10000)  //если прошло 10 секунд, со времени последнего изменения old_time 
    {
    old_time = new_time; // сохраним время
    analogWrite(PIN_alarm_LED, brightness++);
    } 

 

serenka
Offline
Зарегистрирован: 08.03.2017

Добрый день. Извините, что влез в Вашу тему со своим вопросом, но просто не хотелось плодить новую. Подскажите пожалуйста, никак код не могу написать. Суть в следующем. Есть подсветка лесенки. Все вроде замечательно работает. Решил еще что-то прикрутить, например управление остальным светом. Я так понимаю, столкнусь с проблемой, что из-за пауз delay в лесенке, настанет момент когда какой-то датчик не сможет сработать, т.к. в это время ардуино будет отдыхать. Хочу delay заменить на millis только вот как бы я не старался, не работает. 

Сам код лесенки (не полностью, вместо включения дидов, пока написал чтобы в Serial.print выводил. 

#include <Ultrasonic.h> // подключаем библиотеку Ultrasonic
Ultrasonic Ultrasonic_Bottom_Sensor (6,7); // назначаем выходы для Trig и Echo нижнего сенсора

int Lighting_Stage_1 = 13; // подсветка 1-й лесницы
int Lighting_Stage_2 = 12; // подсветка 2-й лесницы
int Lighting_Stage_3 = 11; // подсветка 3-й лесницы
int Lighting_Stage_4 = 10; // подсветка 4-й лесницы

const byte Length_Step = 100; // Длина ступени

void setup() {
  Serial.begin(9600); }
  
void loop() {
  if (Ultrasonic_Bottom_Sensor.Ranging(CM) < Length_Step) {
    Led_On();}
  else {
  Serial.println ("datchik ne srabotal");
  }
}
void Led_On() {
  Serial.println ("Led 1 on");
  delay(1000);
  Serial.println ("Led 2 on");
  delay(1000);
  Serial.println ("Led 3 on");
  delay(1000);
  Serial.println ("Led 4 on");
  delay(1000);}

Попробовал в функцию Led_On вместо delay ставить код типа 

unsigned long previousMillis = 0;
const long interval = 1000;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;}

ничего не происходит. Задержки нет. все Led 1 on, Led 2 on, Led 3 on, Led 4 on срабатывают моментально, без задержки. Куда этот код вставить, чтобы задержка появилась?

Заранее благодарен.

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

serenka пишет:

Попробовал в функцию Led_On вместо delay ставить код типа 

unsigned long previousMillis = 0;
const long interval = 1000;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;}

ничего не происходит. Задержки нет. все Led 1 on, Led 2 on, Led 3 on, Led 4 on срабатывают моментально, без задержки. Куда этот код вставить, чтобы задержка появилась?

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

while ((currentMillis - previousMillis) < interval) {
    currentMillis = millis();}

только это вам ничего не даст - вместо того чтобы спать в delay(), программа просто будет спать в этом цикле. Чтобы программа не теряла времени в делаях - недостаточно заменить их циклами с миллис - надо всю логику программы переписать по другому.

serenka
Offline
Зарегистрирован: 08.03.2017

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

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

serenka пишет:
Вкратце не сообщите какая логика должна быть?

Банальная логика наручных часов. Тех что без будильника. Занимаешься чем-то и поглядываешь на часы. Как время подошло, то делаешь что надо и возвращаешься продолжать делать что ранее. Так бесконечный loop() это то что МК делает всегда, а millis это часы. На них надо регулярно поглядывать и сравнивать с нужным временем. 

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

или разобраца с https://github.com/DetSimen/Arduino-

я даже памогу. 

serenka
Offline
Зарегистрирован: 08.03.2017

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

serenka
Offline
Зарегистрирован: 08.03.2017

DetSimen пишет:

или разобраца с https://github.com/DetSimen/Arduino-

я даже памогу. 

 

Огромное спасибо за ссылку. Обязательно попробую разобраться. Вроде все расписано. Если что-то будет не понятно, спрошу. 

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

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

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

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

serenka
Offline
Зарегистрирован: 08.03.2017

Здравствуйте. Можно У Вас уточнить. Поломал Ваш код, у меня получилось так: 

#include "uTimerList.h"
extern TTimerList TimerList;

THandle pause;       
void setup() 
{
 Serial.begin(9600);
  pause = TimerList.AddSeconds(pause_1,2); 
}

void pause_1(void)
{
  Serial.println ("ssss");
  }

void loop() 
{
 
}

Сейчас сообщение ssss выводится через 2 секунды. Хотел спросить, а как вставить в loop? Если просто написать pause_1(); то перестает работать.

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

если вставить в loop() что?

и что значит перестает работать? Симптомы?

serenka
Offline
Зарегистрирован: 08.03.2017

К примеру, вышеприведенный код сейчас выводит текст ssss раз в 2 секунды. Если вставить функцию void pause_1 в loop, то начинает выводить  текст ssss без задержек. 

 

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

ответьте тогда на вопрос, что есть функция loop() и почему у нее такое название?

serenka
Offline
Зарегистрирован: 08.03.2017

Если честно, не вкурсе. При знакомстве с arduino везеде написано, что всю программу нужно писать в loop(). Я так понимаю, это тоже самое, что любая другая функция, только она выводится постоянно не в ручную, а автоматически.

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

мда. 

Я хочу, чтобы Вы, почитав какследовает, ответили на свой вопрос сами. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

serenka, подсказка: эту функцию не нужно вставлять в loop(). Постарайтесь разобраться в том, в чем Вы сейчас "не вкурсе". Пока не разберетесь, в Ардуино Вам делать нечего.

DetSimen, быстренько просмотрел аннотацию по приведенной Вами ссылке, и возникли непонятки. Самое главное - зачем использовать 16-разрядный таймер? Тем более, в Уно он всего один. У нас уже есть таймер 0, который генерит прерывания с практически нужной нам частотой. Из минусов - 2% несоответствие "желаемой" частоте. Из плюсов: свободный 16-разрядный таймер и отсутствие конфликтов с PWM, если такая потребность возникнет.

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

Я делал из двух соображений: на нулевом таймере висят millis и micros, а на втором таймере - tone.  И те и другие функции портить было нельзя, мне нужны были, а PWM мне наоборот, не нужен. К тому же на первом таймере остается свободным канал В еще, на совпадение, можно его тоже к чему-нибудь прикрутить при желании.  В меге список таймеров плавно переехал на Timer5. 

PS я не делаю высокоточные осциллографы, или генераторы или частотомеры, я сторонник того, что каждому - свое. Зато AVR прекрасно справляется с моими тихоживущими домашними поделками. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ну так почему не сделать Ваши "таймеры" на том же таймере 0 заодно с millis и micros, ничего при этом не нарушая, просто добавив к тому, что уже делается, Ваш код? Где-то на форуме эту идею подробно расписывал ЕвгенийП.

Понимаете, из того, что лично Вам нужен tone, но не нужен PWM, совершенно не следует, что у других пользователей будет так же. Скорее - наоборот, PWM используют чаще, чем tone. А с таймером 0 получается универсальное решение, которое ничего не ломает и не ограничивает.

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

Надачитать. Моих познаний пока не хватает. 

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

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

 

serenka
Offline
Зарегистрирован: 08.03.2017

andriano пишет:

serenka, подсказка: эту функцию не нужно вставлять в loop(). Постарайтесь разобраться в том, в чем Вы сейчас "не вкурсе". Пока не разберетесь, в Ардуино Вам делать нечего.

 

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

serenka
Offline
Зарегистрирован: 08.03.2017

Вдруг кому пригодится. На этом форуме к сожалению я ответа не нашел. Сейчас сделано так, вроде все работает. Единственное человек посоветовал заменить 

millis() > (time + 1000);

на 

millis() - time > 1000;
#include <Ultrasonic.h> // подключаем библиотеку Ultrasonic
 
Ultrasonic Ultrasonic_Bottom_Sensor (6,7); // назначаем выходы для Trig и Echo нижнего сенсора
 
const byte Length_Step = 100; // Длина ступени
unsigned long time;
int flag = 0;
 
void setup() {
  Serial.begin(9600);
}
 
void loop() {
    if (flag == 0)
        if (Ultrasonic_Bottom_Sensor.Ranging(CM) < Length_Step) {
            time = millis();
            flag = 1;
        }
        else   Serial.println ("datchik ne srabotal");
  
    if (flag == 1) Led_On();
}
 
int state = 0;
void Led_On() {
    switch (state) {
        case 0:
            if (millis() > (time + 1000)) {
                Serial.println ("Led 1 on");
                state = 1;
            }
            break;
        case 1: 
            if (millis() > (time + 2000)) {
                Serial.println ("Led 2 on");
                state = 2;
            }
            break;
        case 2: 
            if (millis() > (time + 3000)) {
                Serial.println ("Led 3 on");
                state = 3;
            }
            break;
        case 3 
            if (millis() > (time + 4000)) {
                Serial.println ("Led 4 on");
                state = 0;
                flag = 0;
            }
            break;
    }
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

В посте №15 Вы пишете:

serenka пишет:

Если честно, не вкурсе.

А в посте №23 спрашиваете у меня:

serenka пишет:

Подскажите пожалуйста, в чем конкретно я "не вкурсе"?

А я почем знаю?

Цитата:

что писать в Loop. а что нет? а опрос датчиков в loop тоже не нужно вставлять? Если нужно, тогда где нужно в коде написать, чтобы диоды загорались и выводилась задержка из функции? 

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

serenka
Offline
Зарегистрирован: 08.03.2017

Под "я не в курсе" - я имел ввиду. что я не знаю как дословно переводится loop. Если не врет транслит. то переводится как петля. У DetSimen я хотел спросить, как мне его функцию вставить в loop. Т.к. весь код у меня написан в loop. В определенный момент в функции loop мне нужно было вместо delay вывести его функцию. Мои функции я вывожу в loop к примеру Led_Pin(); и все прекрасно работает. При попытке тоже самое проделать с его функцией, это не работало. Именно это я и хотел у него узнать. Вместо этого был отправлен учить что такое loop. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Правильно переводит.

2. Если тспользуете метод, предложенный DetSimen, функции не нужно вставлять в loop().

 

 

Если Вам нужно переместиться из пункта А в пункт Б, это можно сделать либо на собственном автомобиле, либо на автобусе. Но одновременно - не получится: Вас в автобус с автомобилем никто не пустит.

serenka
Offline
Зарегистрирован: 08.03.2017

Добрый вечер. Решил заменить ради эксперемента delay в коде к сенсору hc-sr04 на millis. Хотел спросить, правильно ли код написал и можно ли так делать? Работает вроде верно (по сравнению со стандартным скетчем который с delay

Оригинал кода

void setup() { 
  Serial.begin (9600); 
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT); 
} 
 
void loop() { 
  int duration, cm; 
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2); 
  digitalWrite(trigPin, HIGH); 
  delayMicroseconds(10); 
  digitalWrite(trigPin, LOW); 
  duration = pulseIn(echoPin, HIGH); 
  cm = duration / 58;
  Serial.print(cm); 
  Serial.println(" cm"); 
  delay(100);
}

Мой код на millis

void loop()
{ 

   Down_Sensor();
   Up_Sensor();  
}

void Down_Sensor()
{
  digitalWrite(Sensor_Bottom_Trig, LOW); 
  Time_Sensor_Steps = micros();
  if(Time_Sensor_Steps - previousMillis > interval_2micro)
  {
    previousMillis = Time_Sensor_Steps;
    digitalWrite(Sensor_Bottom_Trig, HIGH); 
    Time_Sensor_Steps = micros();
    if(Time_Sensor_Steps - previousMillis > interval_10micro)
    {
      previousMillis = Time_Sensor_Steps;
      digitalWrite(Sensor_Bottom_Trig, LOW); 
      duration = pulseIn(Sensor_Bottom_Echo, HIGH); 
      cm = duration / 58;
      Serial.print(cm); 
      Serial.println(" cm Down");
    } 
  }
}
void Up_Sensor()
{
  digitalWrite(Sensor_Up_Trig, LOW); 
  Time_Sensor_Steps = micros();
  if(Time_Sensor_Steps - previousMillis > interval_2micro)
  {
    previousMillis = Time_Sensor_Steps;
    digitalWrite(Sensor_Up_Trig, HIGH); 
    Time_Sensor_Steps = micros();
    if(Time_Sensor_Steps - previousMillis > interval_10micro)
    {
      previousMillis = Time_Sensor_Steps;
      digitalWrite(Sensor_Up_Trig, LOW); 
      duration = pulseIn(Sensor_Up_Echo, HIGH); 
      cm = duration / 58;
      Serial.print(cm); 
      Serial.println(" cm Up");
    } 
  }

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

10cm Down
25cm Up
10cm Down
25cm Up
и т.д. а сейчас шлет 
25 cm Up
10 cm Down
25 cm Up
10 cm Down
10 cm Down
25 cm Up
10 cm Down
25 cm Up
10 cm Down
25 cm Up
25 cm Up
10 cm Down
10 cm Down
10 cm Down
10 cm Down
 
 
b707
Offline
Зарегистрирован: 26.05.2017

serenka, вы пишете о millis(), а используете micros(). Вы уверены. что вам нужны микросекунды?

serenka
Offline
Зарегистрирован: 08.03.2017

Да. там в настройках датчика нужна задержка именно в микросекундах. Я имел ввиду сам код. Возможно так делать? Или это приведет к каким-то плачевным последствиям? К примеру с другими датчиками нельзя такое делать, или когда много кода будет, будут ошибки вылезать и т.п.

serenka
Offline
Зарегистрирован: 08.03.2017

П.С. Чтобы не плодить тему, вдруг кто-то сталкивался. Написал код: К примеру который выше. Все работает быстро, правильно. Стер этот код, написал другой. Стер другой, вставил точь в точь предыдущий код, работает с задержками. Как конкретный пример, Фоторезистр показывал в порт значения (без всяких задержек). Вставил этот же код (с фоторезистром), в порт теперь с какими-то паузами выдает. Штук 10-20 значений моментально выдает, потом на полсекунды запинается, начинает выводить значение примерно в полсекунды. Т.е. какие-то паузы возникают.

Это бракованность ардуины или такое нормально? Просто не только с фоторезистором такое. были проблемы и датчиками HC-SR04 код неделями работает нормально, потом стираю, что-то другое заливаю, стираю, заного тот же код (с ультразвуковыми датчиками) заливаю, а они начинают медленнее работать. Заного код пересобираешь, опять работают нормально.

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

serenka пишет:

Заного код пересобираешь, опять работают нормально.

что значит "пересобираешь код заново"? И в чем отличие от процедуры загрузки, когда не "пересобираете"?

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

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