Плавное увеличение и уменьшение значения без delay

jeraf4eg
Offline
Зарегистрирован: 13.01.2018

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

Суть проблеммы:

Есть значение, которое нужно увеличить за необходимое время без использования delay потом сделать задержку, снова поднять, затем опустить его на 0 и запустить процесс по новой. Более наглядно, нужно что бы переменная h за 10 секунд постепенно увеличилась до 100, потом задержка 10 секунд, снова подъем до 200, задержка, подъем до 300 и опускание в 0.

Есть определенные наработки:

 

int time = 5;              //время в секундах
int number = 99;           //количество изменений за время time
int number2 = 199;         //количество изменений за время time
int number3 = 299;         //количество изменений за время time

int segment;                //время между изменениями
unsigned long prev_time;
unsigned long wait_time;
unsigned long wait_time2;
unsigned long wait_time3;      
int h = 0;                  //переменная которую увеличиваем

void setup() {
  segment = (time*1000)/number;
  prev_time = millis();
  Serial.begin(9600);
}


void loop() {
if (((millis()-prev_time) >=segment)&&h<=number){                 //если разница между текущим временем и временем больше заданого интервала(segment) и высота мееньше нужного количества изменений, то:
h++;                                                              //увеличиваем высоту на 1
prev_time=millis();                                               //присваеваем переменной текущее время(фактически время окончания выполнения условия)
Serial.println(h);                                                //вывод
wait_time=millis()+10000;                                         //присвоение времени ожидания теекущего времени + 10 секунд
return;
}
if(((millis()-prev_time) >=segment)&&h<=number2&&wait_time<=millis())   //тоже условие + если переменная wait_time(из прошлого условия) равна или меньше текущего времени > выполняем условия
{h++;
prev_time=millis();
Serial.println(h);
wait_time2=millis()+10000;
return;
}
if(((millis()-prev_time) >=segment)&&h<=number3&&wait_time2<=millis())
{h++;
prev_time=millis();
Serial.println(h);
wait_time3 = millis()+10000;
return;
}

}

Тут с задержками я поднимаю переменную до 300, но теперь не могу додуматься, как мне её опустить до 0 и запустить цикл снова?

Питал идею с этого обсуждения http://arduino.ru/forum/programmirovanie/uvelichenie-znacheniya-peremennoi

Заранее благодарен за Ваше время!

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

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

 

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

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

Попробуйте освоить регулярное программирование автоматов. Эизнь сразу станет намного легче.

Для разминки почитайте вот эту тему. Там, в №12 начинается объяснение, что такое автомат, а в №19 уже приведена готовая программа для автомата Мили. А так, по теме разбросаны очень серьёхные поянения о ток как надо и как не надо проектироваь программу. Почитайте, может потом захотите погуглить на эту тему.

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

О, кстати, jeraf4eg, коллега Вам говорит тоже, что и я

sadman41 пишет:

было бы неплохо завести переменную, которая бы отражала текущий этап. 

Эта переменная называется "состояние автомата". В общем, читайте тему, что я дал, надеюсь, поможет.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

jeraf4eg пишет:

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

Суть проблеммы:

Есть значение, которое нужно увеличить за необходимое время без использования delay потом сделать задержку, снова поднять, затем опустить его на 0 и запустить процесс по новой. Более наглядно, нужно что бы переменная h за 10 секунд постепенно увеличилась до 100, потом задержка 10 секунд, снова подъем до 200, задержка, подъем до 300 и опускание в 0.

Может так


uint32_t time;
uint16_t pausa = 100;
byte(f_vk) = 0;
uint16_t h = 0;


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

void loop() {
  if (!f_vk) {
    if (h == 100 || h == 200 || h == 300) {
      pausa = 10000;
      f_vk = 1;
    }
  }

  if (millis() - time >= pausa) {
    if (f_vk) {
      f_vk = 0;
      pausa = 100;
    }
    h++;
    if (h > 300)h = 0;
    time = millis();
    Serial.println(h);
  }
}

 

jeraf4eg
Offline
Зарегистрирован: 13.01.2018

Спасибо большое, один вопрос, а возможно ли сделать тут так, что бы при достижении 300 значение не "прыгало" на 0 а плавно спустилось (300 299 298...) ?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

jeraf4eg пишет:

Спасибо большое, один вопрос, а возможно ли сделать тут так, что бы при достижении 300 значение не "прыгало" на 0 а плавно спустилось (300 299 298...) ?

Канешно можно! Добавляем еще одну переменныю и и делаем еще одну проверку!

jeraf4eg
Offline
Зарегистрирован: 13.01.2018

Честно говоря, я темный, можно попросить Вас это сделать, или хотя бы коментарии к своему коду написать, а то я как-то не могу понять как, что и к чему? =/

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Диржите - в честь нового года, если надо откоментироать то чуть позже!

uint32_t time;
uint16_t pausa = 100;
bool f_vk = 0;
bool f_nap = 0;
uint16_t h = 0;

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

void loop() {
  if (!f_vk) {
    if (h == 0 || h == 100 || h == 200 || h == 300) {
      pausa = 10000;
      f_vk = 1;
    }
  }

  if (millis() - time >= pausa) {
    if (f_vk) {
      f_vk = 0;
      pausa = 100;
    }
    if(!f_nap)    h++;
    else h--;
    if (h > 300)f_nap = 1;
    if(h == 0)f_nap = 0;
    time = millis();
    Serial.println(h);
  }
}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
uint32_t time; //Переменная для проверки времени
uint16_t pausa = 100; // Это период с каким будем прибавлять или ждать
bool f_vk = 0; // Флаг - для (++/--) или ждем 10сек
bool f_nap = 0; //Флаг - если ==0 (++) а если ==1 (--)
uint16_t h = 0;//Ваша переменная

void setup() {
  Serial.begin(9600);
//  time = millis(); //Это можно закоментировать
}

void loop() {
  if (!f_vk) {  //Сделано чтобы вовремя паузы сюда не заходить
    if (h == 0 || h == 100 || h == 200 || h == 300) { //Если истина вк.паузу
      pausa = 10000; //Переменная была 100 стала 10000
      f_vk = 1; // 
    }
  }

  if (millis() - time >= pausa) { // Проверяем прошло ли время
    if (f_vk) { //Если pausa была 10000 - возвращаем 100
      f_vk = 0;
      pausa = 100;
    }
    if(!f_nap) h++; // если направление ==0 (++)
    else h--; // иначе (--)
    if (h > 300)f_nap = 1; // Если достигли 300 меняем направление (--)
    if(h == 0)f_nap = 0; // Если достигли 0 меняем (++)
    time = millis(); // засекаем время
    Serial.println(h);
  }
}

 

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

вот эта конструкция 

if (h == 0 || h == 100 || h == 200 || h == 300)

меняется на 

if (!(h % 100)) ...

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

if (h>=300) ...

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

DetSimen пишет:

вот эта конструкция 

if (h == 0 || h == 100 || h == 200 || h == 300)

меняется на 

if (!(h % 100)) ...

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

if (h>=300) ...

 

Согласен.  А еще можно убрать переменную (bool f_vk = 0;) Выражаясь словами Евгения, "любое улутшение кода есть предпоследнее" И тогда код будет выглятедь так

uint32_t time;
uint16_t pausa = 100;
bool f_nap = 0;
uint16_t h = 0;

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

void loop() {
  if (!(h % 100)) pausa = 10000;

  if (millis() - time >= pausa) {
    if (pausa > 100) pausa = 100;
    if(!f_nap) h++;
    else h--;
    if (h >= 300)f_nap = 1;
    if(h == 0)f_nap = 0;
    time = millis();
    Serial.println(h);
  }
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Через месяцок без поллитры не разберешься в логике вашего кода...

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Намек понял! Начинаю создавать ЗАПАСЫ.